From 5d3177b0bad8868473ce2ae9db8be20bab6ce357 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 7 Oct 2023 15:33:08 +0200 Subject: [PATCH 01/14] Updated code formatting --- Epoch.net/Constants.cs | 21 +- Epoch.net/DateTimeExtensions.cs | 131 +++++---- Epoch.net/DefaultTimeProvider.cs | 9 +- Epoch.net/EpochTime.cs | 333 +++++++++++------------ Epoch.net/EpochTimeValueException.cs | 45 ++- Epoch.net/ITimeProvider.cs | 9 +- Epoch.net/IntExtensions.cs | 95 ++++--- Epoch.net/LongEpochTime.cs | 325 +++++++++++----------- Epoch.net/LongEpochTimeValueException.cs | 15 +- Epoch.net/LongExtensions.cs | 119 ++++---- Epoch.net/TimeSpanExtensions.cs | 153 ++++++----- 11 files changed, 622 insertions(+), 633 deletions(-) diff --git a/Epoch.net/Constants.cs b/Epoch.net/Constants.cs index 5009a55..55e74ec 100644 --- a/Epoch.net/Constants.cs +++ b/Epoch.net/Constants.cs @@ -1,15 +1,14 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +public static class Constants { - public static class Constants - { - public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - public const int MIN_VALUE_INT = -2147483648; - public const int MAX_VALUE_INT = 2147483647; - public static readonly DateTime MAX_VALUE_DATETIME = new DateTime(2038, 1, 19,3,14,07, DateTimeKind.Utc); // 3:14:07 Tuesday, 19 January 2038 UTC - public static readonly DateTime MIN_VALUE_DATETIME = new DateTime(1901, 12, 13, 20, 45, 52, DateTimeKind.Utc); // 20:45:52 Friday, 13 December 1901 UTC - public const long MAX_VALUE_LONG = 922337203685477; - public const long MIN_VALUE_LONG = -922337203685477; - } + public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + public const int MIN_VALUE_INT = -2147483648; + public const int MAX_VALUE_INT = 2147483647; + public static readonly DateTime MAX_VALUE_DATETIME = new DateTime(2038, 1, 19,3,14,07, DateTimeKind.Utc); // 3:14:07 Tuesday, 19 January 2038 UTC + public static readonly DateTime MIN_VALUE_DATETIME = new DateTime(1901, 12, 13, 20, 45, 52, DateTimeKind.Utc); // 20:45:52 Friday, 13 December 1901 UTC + public const long MAX_VALUE_LONG = 922337203685477; + public const long MIN_VALUE_LONG = -922337203685477; } \ No newline at end of file diff --git a/Epoch.net/DateTimeExtensions.cs b/Epoch.net/DateTimeExtensions.cs index 1674b66..998f37c 100644 --- a/Epoch.net/DateTimeExtensions.cs +++ b/Epoch.net/DateTimeExtensions.cs @@ -1,82 +1,81 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +/// +/// Implements utility methods on the structure +/// +public static class DateTimeExtensions { /// - /// Implements utility methods on the structure + /// Transforms the given into a LongEpochTimestamp /// - public static class DateTimeExtensions + /// The structure to convert into an LongEpochTimestamp + /// The number of milliseconds since 1970-01-01T00:00Z + /// The LongEpochTimestamp is the number of milliseconds since 1970-01-01T00:00Z + public static long ToLongEpochTimestamp(this DateTime dateTime) { - /// - /// Transforms the given into a LongEpochTimestamp - /// - /// The structure to convert into an LongEpochTimestamp - /// The number of milliseconds since 1970-01-01T00:00Z - /// The LongEpochTimestamp is the number of milliseconds since 1970-01-01T00:00Z - public static long ToLongEpochTimestamp(this DateTime dateTime) - { - var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - Constants.UnixEpoch; - - return Convert.ToInt64(timeSinceDisco.TotalMilliseconds); - } + var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - Constants.UnixEpoch; + + return Convert.ToInt64(timeSinceDisco.TotalMilliseconds); + } - /// - /// Transforms the given into the EpochTimestamp - /// - /// The structure to convert into a EpochTimestamp - /// The number of seconds since 1970-01-01T00:00Z - /// - /// If the exceeded the valid range of a Unix Epoch - /// - /// The EpochTimestamp is the number of seconds since the 1970-01-01T00:00Z - public static int ToEpochTimestamp(this DateTime dateTime) + /// + /// Transforms the given into the EpochTimestamp + /// + /// The structure to convert into a EpochTimestamp + /// The number of seconds since 1970-01-01T00:00Z + /// + /// If the exceeded the valid range of a Unix Epoch + /// + /// The EpochTimestamp is the number of seconds since the 1970-01-01T00:00Z + public static int ToEpochTimestamp(this DateTime dateTime) + { + if (!dateTime.IsValidEpochTime()) { - if (!dateTime.IsValidEpochTime()) - { - throw new EpochTimeValueException(dateTime); - } - - var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - Constants.UnixEpoch; - - return Convert.ToInt32(timeSinceDisco.TotalSeconds); + throw new EpochTimeValueException(dateTime); } + + var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - Constants.UnixEpoch; + + return Convert.ToInt32(timeSinceDisco.TotalSeconds); + } - /// - /// Transforms the given into a - /// - /// The structure to convert into a - /// A representation of the given structure - /// - /// If the exceeded the valid range of a Unix Epoch - /// - public static EpochTime ToEpochTime(this DateTime dateTime) + /// + /// Transforms the given into a + /// + /// The structure to convert into a + /// A representation of the given structure + /// + /// If the exceeded the valid range of a Unix Epoch + /// + public static EpochTime ToEpochTime(this DateTime dateTime) + { + if (!dateTime.IsValidEpochTime()) { - if (!dateTime.IsValidEpochTime()) - { - throw new EpochTimeValueException(dateTime); - } - - return new EpochTime(dateTime); + throw new EpochTimeValueException(dateTime); } + + return new EpochTime(dateTime); + } - /// - /// Transforms the given into a - /// - /// The structure to convert into a - /// A representation of the given - public static LongEpochTime ToLongEpochTime(this DateTime dateTime) - { - return new LongEpochTime(dateTime); - } + /// + /// Transforms the given into a + /// + /// The structure to convert into a + /// A representation of the given + public static LongEpochTime ToLongEpochTime(this DateTime dateTime) + { + return new LongEpochTime(dateTime); + } - /// - /// Determines if the given is in a valid range - /// - /// The structure to test - /// True if the is in a valid range, False if not - public static bool IsValidEpochTime(this DateTime dateTime) - { - return dateTime >= Constants.MIN_VALUE_DATETIME && dateTime <= Constants.MAX_VALUE_DATETIME; - } + /// + /// Determines if the given is in a valid range + /// + /// The structure to test + /// True if the is in a valid range, False if not + public static bool IsValidEpochTime(this DateTime dateTime) + { + return dateTime >= Constants.MIN_VALUE_DATETIME && dateTime <= Constants.MAX_VALUE_DATETIME; } } \ No newline at end of file diff --git a/Epoch.net/DefaultTimeProvider.cs b/Epoch.net/DefaultTimeProvider.cs index 5a6d37d..92c2801 100644 --- a/Epoch.net/DefaultTimeProvider.cs +++ b/Epoch.net/DefaultTimeProvider.cs @@ -1,9 +1,8 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +public class DefaultTimeProvider : ITimeProvider { - public class DefaultTimeProvider : ITimeProvider - { - public DateTime UtcNow => DateTime.UtcNow; - } + public DateTime UtcNow => DateTime.UtcNow; } \ No newline at end of file diff --git a/Epoch.net/EpochTime.cs b/Epoch.net/EpochTime.cs index eb99c58..53f6d1e 100644 --- a/Epoch.net/EpochTime.cs +++ b/Epoch.net/EpochTime.cs @@ -1,208 +1,207 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +/// +/// Implements a to the second precise unix timestamp +/// +public sealed class EpochTime { + static EpochTime() + { + TimeProvider = new DefaultTimeProvider(); + } + + private static ITimeProvider TimeProvider { get; set; } + + #region Constructors + + /// + /// Creates a new instance of with a given rawEpoch + /// + /// The number of seconds from 1970-01-01T00:00:00 + public EpochTime(int rawEpoch) + { + this.rawEpoch = rawEpoch; + } + /// - /// Implements a to the second precise unix timestamp + /// Creates a new instance of with the given /// - public sealed class EpochTime + /// The used to initialize the + /// + /// If the passed is outside of the valid Epoch range + /// + /// + /// The given is converted to UTC according to the environment settings + /// + public EpochTime(DateTime dateTime) { - static EpochTime() + if (!dateTime.IsValidEpochTime()) { - TimeProvider = new DefaultTimeProvider(); + throw new EpochTimeValueException(dateTime); } - - private static ITimeProvider TimeProvider { get; set; } - - #region Constructors - - /// - /// Creates a new instance of with a given rawEpoch - /// - /// The number of seconds from 1970-01-01T00:00:00 - public EpochTime(int rawEpoch) - { - this.rawEpoch = rawEpoch; - } - - /// - /// Creates a new instance of with the given - /// - /// The used to initialize the - /// - /// If the passed is outside of the valid Epoch range - /// - /// - /// The given is converted to UTC according to the environment settings - /// - public EpochTime(DateTime dateTime) - { - if (!dateTime.IsValidEpochTime()) - { - throw new EpochTimeValueException(dateTime); - } - rawEpoch = dateTime.ToEpochTimestamp(); - } + rawEpoch = dateTime.ToEpochTimestamp(); + } - /// - /// Creates a new instance of with the given instance as initialisation data - /// - /// used to initialize the instance - /// If the epoch instance is null - /// - /// Is a simple copy constructor - /// - public EpochTime(EpochTime epoch) + /// + /// Creates a new instance of with the given instance as initialisation data + /// + /// used to initialize the instance + /// If the epoch instance is null + /// + /// Is a simple copy constructor + /// + public EpochTime(EpochTime epoch) + { + if (epoch == null) { - if (epoch == null) - { - throw new ArgumentNullException(nameof(epoch), "The provided epoch can not be null"); - } - - rawEpoch = epoch.Epoch; + throw new ArgumentNullException(nameof(epoch), "The provided epoch can not be null"); } - /// - /// Creates a new instance of with the given as a offset from 1970-01-01T00:00Z - /// - /// The representing the offset from 1970-01-01T00:00Z - /// - /// If the offset would put the outside of the valid Epoch range - /// - public EpochTime(TimeSpan timeSpan) + rawEpoch = epoch.Epoch; + } + + /// + /// Creates a new instance of with the given as a offset from 1970-01-01T00:00Z + /// + /// The representing the offset from 1970-01-01T00:00Z + /// + /// If the offset would put the outside of the valid Epoch range + /// + public EpochTime(TimeSpan timeSpan) + { + if (!timeSpan.IsValidEpochTime()) { - if (!timeSpan.IsValidEpochTime()) - { - throw new EpochTimeValueException(timeSpan); - } - - rawEpoch = timeSpan.ToEpochTimestamp(); + throw new EpochTimeValueException(timeSpan); } - #endregion - private int rawEpoch; + rawEpoch = timeSpan.ToEpochTimestamp(); + } + #endregion - #region Static methods + private int rawEpoch; - /// - /// Injects a new global thread safe instance to be used globally - /// - /// The new time provider instance - public static void SetTimeProvider(ITimeProvider timeProvider) - { - if (timeProvider != null) - { - TimeProvider = timeProvider; - } - } + #region Static methods - /// - /// Resets the global time provider to the default system time provider - /// - public static void ResetTimeProvider() + /// + /// Injects a new global thread safe instance to be used globally + /// + /// The new time provider instance + public static void SetTimeProvider(ITimeProvider timeProvider) + { + if (timeProvider != null) { - TimeProvider = new DefaultTimeProvider(); + TimeProvider = timeProvider; } + } - /// - /// Gets the current UTC date and time as an - /// - public static EpochTime Now => TimeProvider.UtcNow.ToEpochTime(); - - - #endregion - + /// + /// Resets the global time provider to the default system time provider + /// + public static void ResetTimeProvider() + { + TimeProvider = new DefaultTimeProvider(); + } - /// - /// Gets a representation of the instance - /// - public int Epoch => rawEpoch; + /// + /// Gets the current UTC date and time as an + /// + public static EpochTime Now => TimeProvider.UtcNow.ToEpochTime(); + + + #endregion + - /// - /// Returns a representation of the instance - /// - /// A representation of the instance - public DateTime DateTime => rawEpoch.ToDateTime(); - + /// + /// Gets a representation of the instance + /// + public int Epoch => rawEpoch; + + /// + /// Returns a representation of the instance + /// + /// A representation of the instance + public DateTime DateTime => rawEpoch.ToDateTime(); + + + /// + /// Returns a representation of the instance + /// + /// A representation of the instance + public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); + + #region Epoch manipulation + + /// + /// Applies the given offset to the instance + /// + /// The offset to apply + /// The updated instance + /// + /// The method returns an updated but also updates the calling instance + /// + public EpochTime Add(TimeSpan span) + { + var newSpan = this.TimeSpan + span; + rawEpoch = newSpan.ToEpochTimestamp(); + return this; + } + + #endregion + + #region Operators + + public static EpochTime operator +(EpochTime operand1, EpochTime operand2) + { + var epochSum = operand1.Epoch + (long)operand2.Epoch; - /// - /// Returns a representation of the instance - /// - /// A representation of the instance - public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); - - #region Epoch manipulation - - /// - /// Applies the given offset to the instance - /// - /// The offset to apply - /// The updated instance - /// - /// The method returns an updated but also updates the calling instance - /// - public EpochTime Add(TimeSpan span) + if (!epochSum.IsValidEpochTimestamp()) { - var newSpan = this.TimeSpan + span; - rawEpoch = newSpan.ToEpochTimestamp(); - return this; + throw new EpochTimeValueException(epochSum); } - #endregion - - #region Operators + return new EpochTime(Convert.ToInt32(epochSum)); + } - public static EpochTime operator +(EpochTime operand1, EpochTime operand2) - { - var epochSum = operand1.Epoch + (long)operand2.Epoch; - - if (!epochSum.IsValidEpochTimestamp()) - { - throw new EpochTimeValueException(epochSum); - } - - return new EpochTime(Convert.ToInt32(epochSum)); - } + public static EpochTime operator -(EpochTime operand1, EpochTime operand2) + { + var epochSub = operand1.Epoch - (long) operand2.Epoch; - public static EpochTime operator -(EpochTime operand1, EpochTime operand2) + if (!epochSub.IsValidEpochTimestamp()) { - var epochSub = operand1.Epoch - (long) operand2.Epoch; - - if (!epochSub.IsValidEpochTimestamp()) - { - throw new EpochTimeValueException(epochSub); - } - - return new EpochTime(operand1.Epoch - operand2.Epoch); + throw new EpochTimeValueException(epochSub); } - #endregion + + return new EpochTime(operand1.Epoch - operand2.Epoch); + } + #endregion - #region Equals + #region Equals - /// - public override bool Equals(object obj) + /// + public override bool Equals(object obj) + { + if (obj is EpochTime comparedEpoch) { - if (obj is EpochTime comparedEpoch) - { - return comparedEpoch.Epoch == Epoch; - } - - return false; + return comparedEpoch.Epoch == Epoch; } - /// - public override int GetHashCode() - { - return Epoch; - } + return false; + } - /// - public override string ToString() - { - return Epoch.ToString(); - } + /// + public override int GetHashCode() + { + return Epoch; + } - #endregion + /// + public override string ToString() + { + return Epoch.ToString(); } + + #endregion } \ No newline at end of file diff --git a/Epoch.net/EpochTimeValueException.cs b/Epoch.net/EpochTimeValueException.cs index a0d25ca..1736a88 100644 --- a/Epoch.net/EpochTimeValueException.cs +++ b/Epoch.net/EpochTimeValueException.cs @@ -1,31 +1,30 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +public class EpochTimeValueException : Exception { - public class EpochTimeValueException : Exception - { - private const string DefaultErrorMessage = "The provided value could not be represented in a Epoch"; - private const string DateTimeErrorMessage = "The DateTime {0} is not in a Epoch range"; - private const string TimeStampErrorMessage = "The Timespan {0} is not in a Epoch range"; - private const string EpochTimeErrorMessage = "The EpochTime {0} is not in a Epoch range"; - private const string LongErrorMessage = "The number {0} is not in a Epoch range"; - - public EpochTimeValueException() - : base(DefaultErrorMessage){} + private const string DefaultErrorMessage = "The provided value could not be represented in a Epoch"; + private const string DateTimeErrorMessage = "The DateTime {0} is not in a Epoch range"; + private const string TimeStampErrorMessage = "The Timespan {0} is not in a Epoch range"; + private const string EpochTimeErrorMessage = "The EpochTime {0} is not in a Epoch range"; + private const string LongErrorMessage = "The number {0} is not in a Epoch range"; + + public EpochTimeValueException() + : base(DefaultErrorMessage){} + + public EpochTimeValueException(string message) + :base(message) {} - public EpochTimeValueException(string message) - :base(message) {} - - public EpochTimeValueException(DateTime value) - :base(string.Format(DateTimeErrorMessage, value)){} + public EpochTimeValueException(DateTime value) + :base(string.Format(DateTimeErrorMessage, value)){} - public EpochTimeValueException(TimeSpan value) - :base(string.Format(TimeStampErrorMessage, value)){} + public EpochTimeValueException(TimeSpan value) + :base(string.Format(TimeStampErrorMessage, value)){} - public EpochTimeValueException(EpochTime value) - :base(string.Format(EpochTimeErrorMessage, value)){} + public EpochTimeValueException(EpochTime value) + :base(string.Format(EpochTimeErrorMessage, value)){} - public EpochTimeValueException(long value) - :base(string.Format(LongErrorMessage, value)){} - } + public EpochTimeValueException(long value) + :base(string.Format(LongErrorMessage, value)){} } \ No newline at end of file diff --git a/Epoch.net/ITimeProvider.cs b/Epoch.net/ITimeProvider.cs index 4b6dd7e..5842471 100644 --- a/Epoch.net/ITimeProvider.cs +++ b/Epoch.net/ITimeProvider.cs @@ -1,9 +1,8 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +public interface ITimeProvider { - public interface ITimeProvider - { - DateTime UtcNow { get; } - } + DateTime UtcNow { get; } } \ No newline at end of file diff --git a/Epoch.net/IntExtensions.cs b/Epoch.net/IntExtensions.cs index d9345a1..09ab406 100644 --- a/Epoch.net/IntExtensions.cs +++ b/Epoch.net/IntExtensions.cs @@ -1,60 +1,59 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +/// +/// Implements based helper methods +/// +public static class IntExtensions { /// - /// Implements based helper methods + /// Transforms the given into a structure /// - public static class IntExtensions + /// The unix epoch + /// A initialized to the given offset in seconds from 1970-01-01T00:00Z + public static DateTime ToDateTime(this int epoch) { - /// - /// Transforms the given into a structure - /// - /// The unix epoch - /// A initialized to the given offset in seconds from 1970-01-01T00:00Z - public static DateTime ToDateTime(this int epoch) - { - return Constants.UnixEpoch.AddSeconds(epoch); - } + return Constants.UnixEpoch.AddSeconds(epoch); + } - /// - /// Transforms the given into a structure - /// - /// The unix epoch - /// A representing the offset of 1970-01-01T00:00Z - public static TimeSpan ToTimeSpan(this int epoch) - { - return TimeSpan.FromSeconds(epoch); - } + /// + /// Transforms the given into a structure + /// + /// The unix epoch + /// A representing the offset of 1970-01-01T00:00Z + public static TimeSpan ToTimeSpan(this int epoch) + { + return TimeSpan.FromSeconds(epoch); + } - /// - /// Transforms the given into a - /// - /// The unix epoch - /// A initialized with the given unix epoch - public static EpochTime ToEpochTime(this int epoch) - { - return new EpochTime(epoch); - } + /// + /// Transforms the given into a + /// + /// The unix epoch + /// A initialized with the given unix epoch + public static EpochTime ToEpochTime(this int epoch) + { + return new EpochTime(epoch); + } - /// - /// Transforms the given into a - /// - /// The unix epoch - /// A initialized with the given unix epoch - public static LongEpochTime ToLongEpochTime(this int epoch) - { - return new LongEpochTime(epoch.ToLongEpochTimestamp()); - } + /// + /// Transforms the given into a + /// + /// The unix epoch + /// A initialized with the given unix epoch + public static LongEpochTime ToLongEpochTime(this int epoch) + { + return new LongEpochTime(epoch.ToLongEpochTimestamp()); + } - /// - /// Transforms the given seconds offset into a millisecond offset - /// - /// The unix epoch - /// The milliseconds from 1970-01-01T00:00Z - public static long ToLongEpochTimestamp(this int epoch) - { - return epoch * 1000L; - } + /// + /// Transforms the given seconds offset into a millisecond offset + /// + /// The unix epoch + /// The milliseconds from 1970-01-01T00:00Z + public static long ToLongEpochTimestamp(this int epoch) + { + return epoch * 1000L; } } \ No newline at end of file diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index 478426f..004ec84 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -1,200 +1,199 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +/// +/// Implements a millisecond precise unix epoch +/// +public sealed class LongEpochTime { + private static ITimeProvider timeProvider; + + static LongEpochTime() + { + timeProvider = new DefaultTimeProvider(); + } + + #region Constructors + /// - /// Implements a millisecond precise unix epoch + /// Initializes a new instance of /// - public sealed class LongEpochTime + /// The from which to initialize the instance + public LongEpochTime(DateTime dateTime) { - private static ITimeProvider timeProvider; + rawEpoch = dateTime.ToLongEpochTimestamp(); + } - static LongEpochTime() - { - timeProvider = new DefaultTimeProvider(); - } - - #region Constructors - - /// - /// Initializes a new instance of - /// - /// The from which to initialize the instance - public LongEpochTime(DateTime dateTime) + /// + /// Initializes a new instance of + /// + /// The number of milliseconds since 1970-01-01T00:00Z + public LongEpochTime(long longEpochTimestamp) + { + rawEpoch = longEpochTimestamp; + } + + /// + /// Initializes a new instance of + /// + /// The offset from 1970-01-01T00:00Z + /// + /// If the is not in a valid range + /// + public LongEpochTime(TimeSpan timeSpan) + { + if (!timeSpan.IsValidLongEpochTime()) { - rawEpoch = dateTime.ToLongEpochTimestamp(); + throw new LongEpochTimeValueException(timeSpan); } - /// - /// Initializes a new instance of - /// - /// The number of milliseconds since 1970-01-01T00:00Z - public LongEpochTime(long longEpochTimestamp) + rawEpoch = timeSpan.ToLongEpochTimestamp(); + } + + /// + /// Initializes a new instance of + /// + /// The from which to take the initialization data + /// + /// If the given is null + /// + public LongEpochTime(LongEpochTime longEpochTime) + { + if (longEpochTime == null) { - rawEpoch = longEpochTimestamp; + throw new ArgumentNullException(nameof(longEpochTime), "The provided LongEpochTime can not be null"); } - /// - /// Initializes a new instance of - /// - /// The offset from 1970-01-01T00:00Z - /// - /// If the is not in a valid range - /// - public LongEpochTime(TimeSpan timeSpan) - { - if (!timeSpan.IsValidLongEpochTime()) - { - throw new LongEpochTimeValueException(timeSpan); - } + rawEpoch = longEpochTime.Epoch; + } - rawEpoch = timeSpan.ToLongEpochTimestamp(); + /// + /// Initializes a new instance of + /// + /// The from which to take the initialization data + /// + /// If the provided is null + /// + public LongEpochTime(EpochTime epochTime) + { + if (epochTime == null) + { + throw new ArgumentNullException(nameof(epochTime), "The provided EpochTime can not be null"); } - /// - /// Initializes a new instance of - /// - /// The from which to take the initialization data - /// - /// If the given is null - /// - public LongEpochTime(LongEpochTime longEpochTime) - { - if (longEpochTime == null) - { - throw new ArgumentNullException(nameof(longEpochTime), "The provided LongEpochTime can not be null"); - } + rawEpoch = epochTime.Epoch.ToLongEpochTimestamp(); + } + + #endregion - rawEpoch = longEpochTime.Epoch; - } + private long rawEpoch { get; set; } + + #region Static methods - /// - /// Initializes a new instance of - /// - /// The from which to take the initialization data - /// - /// If the provided is null - /// - public LongEpochTime(EpochTime epochTime) + /// + /// Injects a new global thread safe instance to be used globally + /// + /// The new time provider instance + public static void SetTimeProvider(ITimeProvider timeProvider) + { + if (timeProvider != null) { - if (epochTime == null) - { - throw new ArgumentNullException(nameof(epochTime), "The provided EpochTime can not be null"); - } - - rawEpoch = epochTime.Epoch.ToLongEpochTimestamp(); + LongEpochTime.timeProvider = timeProvider; } - - #endregion + } - private long rawEpoch { get; set; } - - #region Static methods + /// + /// Resets the global time provider to the default system time provider + /// + public static void ResetTimeProvider() + { + timeProvider = new DefaultTimeProvider(); + } - /// - /// Injects a new global thread safe instance to be used globally - /// - /// The new time provider instance - public static void SetTimeProvider(ITimeProvider timeProvider) - { - if (timeProvider != null) - { - LongEpochTime.timeProvider = timeProvider; - } - } + /// + /// Gets the current UTC date and time as an + /// + public static LongEpochTime Now => timeProvider.UtcNow.ToLongEpochTime(); - /// - /// Resets the global time provider to the default system time provider - /// - public static void ResetTimeProvider() - { - timeProvider = new DefaultTimeProvider(); - } + #endregion + + #region Public methods + + /// + /// Gets a millisecond unix epoch representation of the instance + /// + public long Epoch => rawEpoch; - /// - /// Gets the current UTC date and time as an - /// - public static LongEpochTime Now => timeProvider.UtcNow.ToLongEpochTime(); + /// + /// Get a representation of the instance + /// + public DateTime DateTime => rawEpoch.ToDateTime(); - #endregion - - #region Public methods - - /// - /// Gets a millisecond unix epoch representation of the instance - /// - public long Epoch => rawEpoch; - - /// - /// Get a representation of the instance - /// - public DateTime DateTime => rawEpoch.ToDateTime(); - - /// - /// Get a representation of the instance - /// - public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); - - /// - /// Applies the given offset to the instance - /// - /// The offset to apply - /// The updated instance - /// - /// The method returns an updated but also updates the calling instance - /// - public LongEpochTime Add(TimeSpan timeSpan) - { - var newSpan = TimeSpan + timeSpan; - rawEpoch = newSpan.ToLongEpochTimestamp(); - return this; - } + /// + /// Get a representation of the instance + /// + public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); - #endregion - - #region Operators + /// + /// Applies the given offset to the instance + /// + /// The offset to apply + /// The updated instance + /// + /// The method returns an updated but also updates the calling instance + /// + public LongEpochTime Add(TimeSpan timeSpan) + { + var newSpan = TimeSpan + timeSpan; + rawEpoch = newSpan.ToLongEpochTimestamp(); + return this; + } - public static LongEpochTime operator +(LongEpochTime operator1, LongEpochTime operator2) - { - // todo: There is a open issue with long number overflow - - return new LongEpochTime(operator1.Epoch + operator2.Epoch); - } + #endregion + + #region Operators - public static LongEpochTime operator -(LongEpochTime operator1, LongEpochTime operator2) - { - //todo: There is a open issue with long number underflow - - return new LongEpochTime(operator1.Epoch - operator2.Epoch); - } - - #endregion + public static LongEpochTime operator +(LongEpochTime operator1, LongEpochTime operator2) + { + // todo: There is a open issue with long number overflow - #region Overriden methods + return new LongEpochTime(operator1.Epoch + operator2.Epoch); + } + + public static LongEpochTime operator -(LongEpochTime operator1, LongEpochTime operator2) + { + //todo: There is a open issue with long number underflow - /// - public override int GetHashCode() - { - return rawEpoch.GetHashCode(); - } + return new LongEpochTime(operator1.Epoch - operator2.Epoch); + } + + #endregion + + #region Overriden methods + + /// + public override int GetHashCode() + { + return rawEpoch.GetHashCode(); + } - /// - public override bool Equals(object obj) + /// + public override bool Equals(object obj) + { + if (obj is LongEpochTime comparedEpoch) { - if (obj is LongEpochTime comparedEpoch) - { - return comparedEpoch.Epoch == Epoch; - } - - return false; + return comparedEpoch.Epoch == Epoch; } - /// - public override string ToString() - { - return Epoch.ToString(); - } + return false; + } - #endregion + /// + public override string ToString() + { + return Epoch.ToString(); } + + #endregion } \ No newline at end of file diff --git a/Epoch.net/LongEpochTimeValueException.cs b/Epoch.net/LongEpochTimeValueException.cs index c55af67..af0d2de 100644 --- a/Epoch.net/LongEpochTimeValueException.cs +++ b/Epoch.net/LongEpochTimeValueException.cs @@ -1,14 +1,13 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +public class LongEpochTimeValueException : Exception { - public class LongEpochTimeValueException : Exception + private const string TimeSpanErrorMessage = "The provided TimeSpan {0} does not conform to the LongEpochTime range"; + + public LongEpochTimeValueException(TimeSpan value) + :base(string.Format(TimeSpanErrorMessage, value)) { - private const string TimeSpanErrorMessage = "The provided TimeSpan {0} does not conform to the LongEpochTime range"; - - public LongEpochTimeValueException(TimeSpan value) - :base(string.Format(TimeSpanErrorMessage, value)) - { - } } } \ No newline at end of file diff --git a/Epoch.net/LongExtensions.cs b/Epoch.net/LongExtensions.cs index d732db2..07a42ac 100644 --- a/Epoch.net/LongExtensions.cs +++ b/Epoch.net/LongExtensions.cs @@ -1,74 +1,73 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +/// +/// Implements helper method in the value type +/// +public static class LongExtensions { /// - /// Implements helper method in the value type + /// Determines if the given LongEpochTimestamp is in the valid range for a /// - public static class LongExtensions + /// The LongEpochTimestamp + /// + /// True if the EpochTimestamp is in a valid EpochTime range, False if not + /// + public static bool IsValidEpochTimestamp(this long epoch) { - /// - /// Determines if the given LongEpochTimestamp is in the valid range for a - /// - /// The LongEpochTimestamp - /// - /// True if the EpochTimestamp is in a valid EpochTime range, False if not - /// - public static bool IsValidEpochTimestamp(this long epoch) - { - return epoch >= Constants.MIN_VALUE_INT && epoch <= Constants.MAX_VALUE_INT; - } - - /// - /// Transforms the LongEpochTimestamp into a - /// - /// The LongEpochTimestamp - /// A representation of the given LongEpochTimestamp - public static DateTime ToDateTime(this long value) - { - return Constants.UnixEpoch.AddMilliseconds(value); - } + return epoch >= Constants.MIN_VALUE_INT && epoch <= Constants.MAX_VALUE_INT; + } - /// - /// Transforms the LongEpochTimestamp into a - /// - /// The LongEpochTimestamp - /// The representation of the LongEpochTimestamp - public static TimeSpan ToTimeSpan(this long value) - { - return TimeSpan.FromMilliseconds(value); - } + /// + /// Transforms the LongEpochTimestamp into a + /// + /// The LongEpochTimestamp + /// A representation of the given LongEpochTimestamp + public static DateTime ToDateTime(this long value) + { + return Constants.UnixEpoch.AddMilliseconds(value); + } - /// - /// Transforms the LongEpochTimestamp into a EpochTimestamp - /// - /// The LongEpochTimestamp - /// - /// The LongEpochTimestamp converted from milliseconds to seconds and rounded to the next second - /// - /// - /// If the value is outside of a range - /// - public static int ToEpochTimestamp(this long value) - { - var seconds = value / 1000; + /// + /// Transforms the LongEpochTimestamp into a + /// + /// The LongEpochTimestamp + /// The representation of the LongEpochTimestamp + public static TimeSpan ToTimeSpan(this long value) + { + return TimeSpan.FromMilliseconds(value); + } - if (seconds.IsValidEpochTimestamp()) - { - return Convert.ToInt32(seconds); - } - - throw new EpochTimeValueException(value); - } + /// + /// Transforms the LongEpochTimestamp into a EpochTimestamp + /// + /// The LongEpochTimestamp + /// + /// The LongEpochTimestamp converted from milliseconds to seconds and rounded to the next second + /// + /// + /// If the value is outside of a range + /// + public static int ToEpochTimestamp(this long value) + { + var seconds = value / 1000; - /// - /// Transforms the LongEpochTimestamp into a - /// - /// The LongEpochTimestamp - /// A initialized with the LongEpochTimestamp - public static LongEpochTime ToLongEpochTime(this long value) + if (seconds.IsValidEpochTimestamp()) { - return new LongEpochTime(value); + return Convert.ToInt32(seconds); } + + throw new EpochTimeValueException(value); + } + + /// + /// Transforms the LongEpochTimestamp into a + /// + /// The LongEpochTimestamp + /// A initialized with the LongEpochTimestamp + public static LongEpochTime ToLongEpochTime(this long value) + { + return new LongEpochTime(value); } } \ No newline at end of file diff --git a/Epoch.net/TimeSpanExtensions.cs b/Epoch.net/TimeSpanExtensions.cs index 55a47f7..3317c62 100644 --- a/Epoch.net/TimeSpanExtensions.cs +++ b/Epoch.net/TimeSpanExtensions.cs @@ -1,98 +1,97 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +/// +/// Implements helper methods based on the structure +/// +public static class TimeSpanExtensions { /// - /// Implements helper methods based on the structure + /// Transforms the given into a /// - public static class TimeSpanExtensions + /// The given + /// A new instance initialized with the given + public static EpochTime ToEpochTime(this TimeSpan timeSpan) { - /// - /// Transforms the given into a - /// - /// The given - /// A new instance initialized with the given - public static EpochTime ToEpochTime(this TimeSpan timeSpan) + return new EpochTime(timeSpan); + } + + /// + /// Transforms the given into a EpochTimestamp + /// + /// The given + /// The number of seconds the given represents + /// + /// If the given is not in a valid range + /// + public static int ToEpochTimestamp(this TimeSpan timeSpan) + { + var totalSeconds = timeSpan.TotalSeconds; + + if (!timeSpan.IsValidEpochTime()) { - return new EpochTime(timeSpan); + throw new EpochTimeValueException(timeSpan); } - /// - /// Transforms the given into a EpochTimestamp - /// - /// The given - /// The number of seconds the given represents - /// - /// If the given is not in a valid range - /// - public static int ToEpochTimestamp(this TimeSpan timeSpan) - { - var totalSeconds = timeSpan.TotalSeconds; + return Convert.ToInt32(totalSeconds); + } - if (!timeSpan.IsValidEpochTime()) - { - throw new EpochTimeValueException(timeSpan); - } + /// + /// Transforms the given into a + /// + /// The given + /// A representation of the given + public static LongEpochTime ToLongEpochTime(this TimeSpan timeSpan) + { + return new LongEpochTime(timeSpan); + } - return Convert.ToInt32(totalSeconds); - } + /// + /// Transforms the given into a LongEpochTimestamp + /// + /// The given + /// The milliseconds represented by the given + /// + /// If the number of milliseconds exceeds the range + /// + public static long ToLongEpochTimestamp(this TimeSpan timeSpan) + { + var totalMilliseconds = timeSpan.TotalMilliseconds; - /// - /// Transforms the given into a - /// - /// The given - /// A representation of the given - public static LongEpochTime ToLongEpochTime(this TimeSpan timeSpan) + if (!timeSpan.IsValidLongEpochTime()) { - return new LongEpochTime(timeSpan); + throw new LongEpochTimeValueException(timeSpan); } - /// - /// Transforms the given into a LongEpochTimestamp - /// - /// The given - /// The milliseconds represented by the given - /// - /// If the number of milliseconds exceeds the range - /// - public static long ToLongEpochTimestamp(this TimeSpan timeSpan) - { - var totalMilliseconds = timeSpan.TotalMilliseconds; - - if (!timeSpan.IsValidLongEpochTime()) - { - throw new LongEpochTimeValueException(timeSpan); - } - - return Convert.ToInt64(totalMilliseconds); - } + return Convert.ToInt64(totalMilliseconds); + } - /// - /// Determines if the given is in a valid range - /// - /// The given - /// - /// True if the given is in the valid range, False if not - /// - public static bool IsValidEpochTime(this TimeSpan timeSpan) - { - var totalSeconds = timeSpan.TotalSeconds; + /// + /// Determines if the given is in a valid range + /// + /// The given + /// + /// True if the given is in the valid range, False if not + /// + public static bool IsValidEpochTime(this TimeSpan timeSpan) + { + var totalSeconds = timeSpan.TotalSeconds; - return totalSeconds >= Constants.MIN_VALUE_INT && totalSeconds <= Constants.MAX_VALUE_INT; - } + return totalSeconds >= Constants.MIN_VALUE_INT && totalSeconds <= Constants.MAX_VALUE_INT; + } - /// - /// Determines if the given is in a valid range - /// - /// The given - /// - /// True if the given is in the valid range, False if not - /// - public static bool IsValidLongEpochTime(this TimeSpan timeSpan) - { - var totalMilliseconds = timeSpan.TotalMilliseconds; + /// + /// Determines if the given is in a valid range + /// + /// The given + /// + /// True if the given is in the valid range, False if not + /// + public static bool IsValidLongEpochTime(this TimeSpan timeSpan) + { + var totalMilliseconds = timeSpan.TotalMilliseconds; - return totalMilliseconds >= Constants.MIN_VALUE_LONG && totalMilliseconds <= Constants.MAX_VALUE_LONG; - } + return totalMilliseconds >= Constants.MIN_VALUE_LONG && totalMilliseconds <= Constants.MAX_VALUE_LONG; } } \ No newline at end of file From 2dc48d5eda673f0e0b59270ea551261b2cfe056e Mon Sep 17 00:00:00 2001 From: Dejan Fajfar Date: Sat, 7 Oct 2023 15:39:12 +0200 Subject: [PATCH 02/14] Create dotnet.yml --- .github/workflows/dotnet.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/dotnet.yml diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 0000000..5bbb1e1 --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,28 @@ +# This workflow will build a .NET project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net + +name: .NET + +on: + push: + branches: [ "*" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 7.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal From 4be2655c717a9ca89822d7f7f82d5fe5dc9c54a6 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 7 Oct 2023 15:52:14 +0200 Subject: [PATCH 03/14] Updated target framework --- Epoch.net.Test/Epoch.net.Test.csproj | 2 +- Epoch.net.sln | 26 ++++++++++++++------------ Epoch.net/Epoch.net.csproj | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Epoch.net.Test/Epoch.net.Test.csproj b/Epoch.net.Test/Epoch.net.Test.csproj index b2ee5a3..2becb7e 100644 --- a/Epoch.net.Test/Epoch.net.Test.csproj +++ b/Epoch.net.Test/Epoch.net.Test.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + net7.0;net6.0 false diff --git a/Epoch.net.sln b/Epoch.net.sln index 1b4b6fa..07b8927 100644 --- a/Epoch.net.sln +++ b/Epoch.net.sln @@ -1,20 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.0.0 -MinimumVisualStudioVersion = 10.0.0.1 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{CA9E0DE1-4B2B-43BC-8018-FD520B3721D1}" -ProjectSection(SolutionItems) = preProject - LICENSE = LICENSE - README.md = README.md - .gitignore = .gitignore - appveyor.yml = appveyor.yml - CHANGELOG.md = CHANGELOG.md -EndProjectSection + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + CHANGELOG.md = CHANGELOG.md + LICENSE = LICENSE + README.md = README.md + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epoch.net", "Epoch.net\Epoch.net.csproj", "{FB0FC0E9-E1BC-41CC-BEA1-5F02AE48C82A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epoch.net", "Epoch.net\Epoch.net.csproj", "{FB0FC0E9-E1BC-41CC-BEA1-5F02AE48C82A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epoch.net.Test", "Epoch.net.Test\Epoch.net.Test.csproj", "{CEB262D9-E177-4198-B7E4-9EB826C87F5A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epoch.net.Test", "Epoch.net.Test\Epoch.net.Test.csproj", "{CEB262D9-E177-4198-B7E4-9EB826C87F5A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -34,4 +33,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0527CA42-47FA-41B0-A885-83B2F34FECA1} + EndGlobalSection EndGlobal diff --git a/Epoch.net/Epoch.net.csproj b/Epoch.net/Epoch.net.csproj index e61c401..ceb68d5 100644 --- a/Epoch.net/Epoch.net.csproj +++ b/Epoch.net/Epoch.net.csproj @@ -11,7 +11,7 @@ Implements a simple set of helpers to handle EPOCH timestamps in .NET - netstandard2.0;netcoreapp2.1 + net7.0;net6.0 From e7cf07b77fd4dafc6a5f45cfdee3ba82984b8031 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sun, 8 Oct 2023 16:56:33 +0200 Subject: [PATCH 04/14] Added .net 7 and 8 to the outputs --- .github/workflows/dotnet.yml | 7 +++++-- CHANGELOG.md | 6 ++++++ Epoch.net.sln | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 5bbb1e1..de7fc43 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -1,7 +1,7 @@ # This workflow will build a .NET project # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net -name: .NET +name: BuildAndTest on: push: @@ -19,7 +19,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: | + 8.0.x + 7.0.x + 6.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b2ff92..169e644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [3.2] +### Changed + +- Updated to .net version 7 +- Moved build to github actions + ## [3.1] ### Added diff --git a/Epoch.net.sln b/Epoch.net.sln index 07b8927..d5becfc 100644 --- a/Epoch.net.sln +++ b/Epoch.net.sln @@ -7,6 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{CA9E0DE1-4 ProjectSection(SolutionItems) = preProject .gitignore = .gitignore CHANGELOG.md = CHANGELOG.md + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml LICENSE = LICENSE README.md = README.md EndProjectSection @@ -15,6 +16,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epoch.net", "Epoch.net\Epoc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epoch.net.Test", "Epoch.net.Test\Epoch.net.Test.csproj", "{CEB262D9-E177-4198-B7E4-9EB826C87F5A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildPipelines", "BuildPipelines", "{19F6A183-4FA2-4184-A65D-B89EC4869EF6}" + ProjectSection(SolutionItems) = preProject + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +39,9 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {19F6A183-4FA2-4184-A65D-B89EC4869EF6} = {CA9E0DE1-4B2B-43BC-8018-FD520B3721D1} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0527CA42-47FA-41B0-A885-83B2F34FECA1} EndGlobalSection From 5de163dd3c05975c387180bf5d9c8e9fe1964a9b Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sun, 15 Oct 2023 17:51:36 +0200 Subject: [PATCH 05/14] Manny little changes --- Epoch.net.Test/DateOnlyExtensionsFitxture.cs | 18 ++++++++++++++++++ Epoch.net.Test/Epoch.net.Test.csproj | 7 ++++--- Epoch.net.Test/FakeTimeProvider.cs | 2 +- Epoch.net.Test/TestConstants.cs | 17 +++++++++++++++++ Epoch.net/DateOnlyExtensions.cs | 11 +++++++++++ Epoch.net/DefaultTimeProvider.cs | 5 ++++- Epoch.net/EpochTime.cs | 5 +++-- Epoch.net/IDateTimeProvider.cs | 14 ++++++++++++++ Epoch.net/ITimeProvider.cs | 8 -------- Epoch.net/LongEpochTime.cs | 4 ++-- 10 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 Epoch.net.Test/DateOnlyExtensionsFitxture.cs create mode 100644 Epoch.net.Test/TestConstants.cs create mode 100644 Epoch.net/DateOnlyExtensions.cs create mode 100644 Epoch.net/IDateTimeProvider.cs delete mode 100644 Epoch.net/ITimeProvider.cs diff --git a/Epoch.net.Test/DateOnlyExtensionsFitxture.cs b/Epoch.net.Test/DateOnlyExtensionsFitxture.cs new file mode 100644 index 0000000..1147893 --- /dev/null +++ b/Epoch.net.Test/DateOnlyExtensionsFitxture.cs @@ -0,0 +1,18 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace Epoch.net.Test +{ + [TestClass] + public class DateOnlyExtensionsFitxture + { + + [TestMethod] + public void ToEpoch() + { + DateOnly.FromDateTime(TestConstants.After1970_UTC).ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); + DateOnly.FromDateTime(TestConstants.Before1970_UTC).ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); + } + } +} diff --git a/Epoch.net.Test/Epoch.net.Test.csproj b/Epoch.net.Test/Epoch.net.Test.csproj index 2becb7e..89a901c 100644 --- a/Epoch.net.Test/Epoch.net.Test.csproj +++ b/Epoch.net.Test/Epoch.net.Test.csproj @@ -7,9 +7,10 @@ - - - + + + + diff --git a/Epoch.net.Test/FakeTimeProvider.cs b/Epoch.net.Test/FakeTimeProvider.cs index 995c03b..1566541 100644 --- a/Epoch.net.Test/FakeTimeProvider.cs +++ b/Epoch.net.Test/FakeTimeProvider.cs @@ -2,7 +2,7 @@ namespace Epoch.net.Test { - public class FakeTimeProvider : ITimeProvider + public class FakeTimeProvider : IDateTimeProvider { public const long LONG_EPOCH_TIMESTAMP = 1430906878051; public const int EPOCH_TIMESTAMP = 1430906878; diff --git a/Epoch.net.Test/TestConstants.cs b/Epoch.net.Test/TestConstants.cs new file mode 100644 index 0000000..9a0b533 --- /dev/null +++ b/Epoch.net.Test/TestConstants.cs @@ -0,0 +1,17 @@ +using System; + +namespace Epoch.net.Test +{ + internal static class TestConstants + { + public static readonly DateTime After1970_UTC = new DateTime(2015, 12, 12, 0, 0, 0, DateTimeKind.Utc); + public static readonly DateTime Before1970_UTC = new DateTime(1960, 12, 12, 0, 0, 0, DateTimeKind.Utc); + public static readonly DateTime After1970 = new DateTime(2015, 12, 12, 0, 0, 0, DateTimeKind.Local); + public static readonly DateTime Before1970 = new DateTime(1960, 12, 12, 0, 0, 0, DateTimeKind.Local); + public static readonly DateTime OutOfBounds = new DateTime(2099, 7, 4, 0, 0, 0, DateTimeKind.Utc); + public static readonly int After1970_UTC_Timestamp = 1449878400; + public static readonly long After1970_UTC_LongTimestamp = 1449878400000; + public static readonly int Before1970_UTC_Timestamp = -285724800; + public static readonly long Before1970_UTC_LongTimestamp = -285724800000; + } +} diff --git a/Epoch.net/DateOnlyExtensions.cs b/Epoch.net/DateOnlyExtensions.cs new file mode 100644 index 0000000..fc9d1dd --- /dev/null +++ b/Epoch.net/DateOnlyExtensions.cs @@ -0,0 +1,11 @@ +using System; + +namespace Epoch.net +{ + public static class DateOnlyExtensions + { + public static EpochTime ToEpochTime(this DateOnly date) => date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc).ToEpochTime(); + + public static EpochTime ToEpoctTime(this DateOnly date, TimeOnly time) => date.ToDateTime(time).ToEpochTime(); + } +} diff --git a/Epoch.net/DefaultTimeProvider.cs b/Epoch.net/DefaultTimeProvider.cs index 92c2801..b714ef7 100644 --- a/Epoch.net/DefaultTimeProvider.cs +++ b/Epoch.net/DefaultTimeProvider.cs @@ -2,7 +2,10 @@ namespace Epoch.net; -public class DefaultTimeProvider : ITimeProvider +/// +/// Implemets the system default DateTimeProvider as defined in +/// +public class DefaultTimeProvider : IDateTimeProvider { public DateTime UtcNow => DateTime.UtcNow; } \ No newline at end of file diff --git a/Epoch.net/EpochTime.cs b/Epoch.net/EpochTime.cs index 53f6d1e..7af5a2a 100644 --- a/Epoch.net/EpochTime.cs +++ b/Epoch.net/EpochTime.cs @@ -1,4 +1,5 @@ using System; +using System.Numerics; namespace Epoch.net; @@ -12,7 +13,7 @@ static EpochTime() TimeProvider = new DefaultTimeProvider(); } - private static ITimeProvider TimeProvider { get; set; } + private static IDateTimeProvider TimeProvider { get; set; } #region Constructors @@ -89,7 +90,7 @@ public EpochTime(TimeSpan timeSpan) /// Injects a new global thread safe instance to be used globally /// /// The new time provider instance - public static void SetTimeProvider(ITimeProvider timeProvider) + public static void SetTimeProvider(IDateTimeProvider timeProvider) { if (timeProvider != null) { diff --git a/Epoch.net/IDateTimeProvider.cs b/Epoch.net/IDateTimeProvider.cs new file mode 100644 index 0000000..fe7625a --- /dev/null +++ b/Epoch.net/IDateTimeProvider.cs @@ -0,0 +1,14 @@ +using System; + +namespace Epoch.net; + +/// +/// Defines a date time provides as used by Epoch.net +/// +public interface IDateTimeProvider +{ + /// + /// Gets the current system UTC time + /// + DateTime UtcNow { get; } +} \ No newline at end of file diff --git a/Epoch.net/ITimeProvider.cs b/Epoch.net/ITimeProvider.cs deleted file mode 100644 index 5842471..0000000 --- a/Epoch.net/ITimeProvider.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace Epoch.net; - -public interface ITimeProvider -{ - DateTime UtcNow { get; } -} \ No newline at end of file diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index 004ec84..a2871af 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -7,7 +7,7 @@ namespace Epoch.net; /// public sealed class LongEpochTime { - private static ITimeProvider timeProvider; + private static IDateTimeProvider timeProvider; static LongEpochTime() { @@ -95,7 +95,7 @@ public LongEpochTime(EpochTime epochTime) /// Injects a new global thread safe instance to be used globally /// /// The new time provider instance - public static void SetTimeProvider(ITimeProvider timeProvider) + public static void SetTimeProvider(IDateTimeProvider timeProvider) { if (timeProvider != null) { From d9c4b6e1a2620b60bdd82f8c50fa99e98867c6b5 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sun, 15 Oct 2023 21:48:00 +0200 Subject: [PATCH 06/14] Fixed the build warning --- Epoch.net.Test/EpochTime_Properties_Fixtures.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Epoch.net.Test/EpochTime_Properties_Fixtures.cs b/Epoch.net.Test/EpochTime_Properties_Fixtures.cs index 123e81a..4cda445 100644 --- a/Epoch.net.Test/EpochTime_Properties_Fixtures.cs +++ b/Epoch.net.Test/EpochTime_Properties_Fixtures.cs @@ -48,7 +48,7 @@ public void Add_Negative() } [TestMethod] - public void ToString() + public void ToString_Tests() { Assert.AreEqual(ValidEpochTimestamp.ToString(), ValidEpochTime.ToString()); } From d60f1044e4a82cfa4ea1f655609fd89590566e2c Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sun, 15 Oct 2023 21:49:30 +0200 Subject: [PATCH 07/14] Forgot about the LongEpoch --- Epoch.net.Test/LongEpochTime_Properties_Fixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Epoch.net.Test/LongEpochTime_Properties_Fixture.cs b/Epoch.net.Test/LongEpochTime_Properties_Fixture.cs index ca404ae..d45b556 100644 --- a/Epoch.net.Test/LongEpochTime_Properties_Fixture.cs +++ b/Epoch.net.Test/LongEpochTime_Properties_Fixture.cs @@ -48,7 +48,7 @@ public void Add_Negative() } [TestMethod] - public void ToString() + public void ToString_Tests() { Assert.AreEqual(ValidLongEpochTimestamp.ToString(), ValidLongEpochTime.ToString()); } From b8fdd64757eedc19ba7ea2446e7b91240b35b5fa Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sun, 22 Oct 2023 22:11:46 +0200 Subject: [PATCH 08/14] Lots of little changes --- .editorconfig | 132 +++++++++++++++++++ CHANGELOG.md | 6 + Epoch.net.Test/DateOnlyExtensionsFitxture.cs | 40 +++++- Epoch.net.Test/TimeOnlyExtenjsionsFixture.cs | 14 ++ Epoch.net.sln | 3 + Epoch.net/DateOnlyExtensions.cs | 34 ++++- Epoch.net/Epoch.net.csproj | 1 + Epoch.net/EpochTime.cs | 43 +++--- Epoch.net/LongEpochTime.cs | 52 +++----- Epoch.net/TimeOnlyExtensions.cs | 17 +++ 10 files changed, 290 insertions(+), 52 deletions(-) create mode 100644 .editorconfig create mode 100644 Epoch.net.Test/TimeOnlyExtenjsionsFixture.cs create mode 100644 Epoch.net/TimeOnlyExtensions.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b9711d7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,132 @@ + +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent + +[*.cs] +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent +csharp_style_var_elsewhere = false:silent +csharp_space_around_binary_operators = before_and_after \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 169e644..86ba106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Updated to .net version 7 - Moved build to github actions +- + +### Added + +- DateOnly extensions +- TimeOnly extensions ## [3.1] ### Added diff --git a/Epoch.net.Test/DateOnlyExtensionsFitxture.cs b/Epoch.net.Test/DateOnlyExtensionsFitxture.cs index 1147893..7bb8b19 100644 --- a/Epoch.net.Test/DateOnlyExtensionsFitxture.cs +++ b/Epoch.net.Test/DateOnlyExtensionsFitxture.cs @@ -7,12 +7,48 @@ namespace Epoch.net.Test [TestClass] public class DateOnlyExtensionsFitxture { + private readonly DateOnly After1970_UTC = DateOnly.FromDateTime(TestConstants.After1970_UTC); + private readonly DateOnly Before1970_UTC = DateOnly.FromDateTime(TestConstants.Before1970_UTC); + private readonly DateOnly After1970 = DateOnly.FromDateTime(TestConstants.After1970); + private readonly DateOnly Before1970 = DateOnly.FromDateTime(TestConstants.Before1970); + private readonly DateOnly OutOfBounds = DateOnly.FromDateTime(TestConstants.OutOfBounds); + private readonly TimeOnly RandomTime = new(16, 23, 12); + private readonly int RandomTimeOffset = 58992; + + [TestMethod] + public void ToEpoch_UTC() + { + After1970_UTC.ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); + Before1970_UTC.ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); + } [TestMethod] public void ToEpoch() { - DateOnly.FromDateTime(TestConstants.After1970_UTC).ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); - DateOnly.FromDateTime(TestConstants.Before1970_UTC).ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); + After1970.ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); + Before1970.ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); + } + + [TestMethod] + public void ToEpoch_OutOfBounds() + { + var act = () => OutOfBounds.ToEpochTime().Epoch; + + act.Should().Throw(); + } + + [TestMethod] + public void ToEpoch_WithTime_UTC() + { + After1970_UTC.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp + RandomTimeOffset); + Before1970_UTC.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp + RandomTimeOffset); + } + + [TestMethod] + public void ToEpoch_WithTime() + { + After1970.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp + RandomTimeOffset); + Before1970.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp + RandomTimeOffset); } } } diff --git a/Epoch.net.Test/TimeOnlyExtenjsionsFixture.cs b/Epoch.net.Test/TimeOnlyExtenjsionsFixture.cs new file mode 100644 index 0000000..fbc6bb2 --- /dev/null +++ b/Epoch.net.Test/TimeOnlyExtenjsionsFixture.cs @@ -0,0 +1,14 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Epoch.net.Test +{ + [TestClass] + public class TimeOnlyExtenjsionsFixture + { + } +} diff --git a/Epoch.net.sln b/Epoch.net.sln index d5becfc..bae4584 100644 --- a/Epoch.net.sln +++ b/Epoch.net.sln @@ -5,6 +5,7 @@ VisualStudioVersion = 17.7.34031.279 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{CA9E0DE1-4B2B-43BC-8018-FD520B3721D1}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig .gitignore = .gitignore CHANGELOG.md = CHANGELOG.md .github\workflows\dotnet.yml = .github\workflows\dotnet.yml @@ -21,6 +22,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildPipelines", "BuildPipe .github\workflows\dotnet.yml = .github\workflows\dotnet.yml EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1C689939-5E08-4F0E-A55C-FFADDC607A17}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Epoch.net/DateOnlyExtensions.cs b/Epoch.net/DateOnlyExtensions.cs index fc9d1dd..32ce610 100644 --- a/Epoch.net/DateOnlyExtensions.cs +++ b/Epoch.net/DateOnlyExtensions.cs @@ -4,8 +4,40 @@ namespace Epoch.net { public static class DateOnlyExtensions { + /// + /// Transforms the given structure into a + /// + /// The structure to convert into the + /// + /// A new instance of representaiton of the given structure + /// + /// + /// If the exceeded the valid range of a Unix Epoch + /// public static EpochTime ToEpochTime(this DateOnly date) => date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc).ToEpochTime(); - public static EpochTime ToEpoctTime(this DateOnly date, TimeOnly time) => date.ToDateTime(time).ToEpochTime(); + /// + /// Transforms the given structure into a with the given offset + /// + /// The structure to convert into the + /// The structure used for the time ofdfset from midnight + /// Determines if the given is UTC or local time. TRUE => UTC, FALSE => Local time + /// + /// It is assumed that the is UTC time. Determined by the + /// + /// + /// A new instance of representaiton of the given and structure + /// + /// + /// If the exceeded the valid range of a Unix Epoch + /// + public static EpochTime ToEpochTime(this DateOnly date, TimeOnly time, bool isUtcTime = true) + { + return isUtcTime switch + { + true => date.ToDateTime(time, DateTimeKind.Utc).ToEpochTime(), + false => date.ToDateTime(time, DateTimeKind.Local).ToEpochTime() + }; + } } } diff --git a/Epoch.net/Epoch.net.csproj b/Epoch.net/Epoch.net.csproj index ceb68d5..15111bc 100644 --- a/Epoch.net/Epoch.net.csproj +++ b/Epoch.net/Epoch.net.csproj @@ -18,6 +18,7 @@ https://raw.githubusercontent.com/dejanfajfar/epoch.net/master/images/logo_square_64.png posix unix timestamp epoch datetime timespan library core standard https://github.com/dejanfajfar/epoch.net + True diff --git a/Epoch.net/EpochTime.cs b/Epoch.net/EpochTime.cs index 7af5a2a..9955f75 100644 --- a/Epoch.net/EpochTime.cs +++ b/Epoch.net/EpochTime.cs @@ -1,5 +1,4 @@ using System; -using System.Numerics; namespace Epoch.net; @@ -12,17 +11,17 @@ static EpochTime() { TimeProvider = new DefaultTimeProvider(); } - + private static IDateTimeProvider TimeProvider { get; set; } - + #region Constructors - + /// /// Creates a new instance of with a given rawEpoch /// /// The number of seconds from 1970-01-01T00:00:00 public EpochTime(int rawEpoch) - { + { this.rawEpoch = rawEpoch; } @@ -60,10 +59,10 @@ public EpochTime(EpochTime epoch) { throw new ArgumentNullException(nameof(epoch), "The provided epoch can not be null"); } - + rawEpoch = epoch.Epoch; } - + /// /// Creates a new instance of with the given as a offset from 1970-01-01T00:00Z /// @@ -110,10 +109,10 @@ public static void ResetTimeProvider() /// Gets the current UTC date and time as an /// public static EpochTime Now => TimeProvider.UtcNow.ToEpochTime(); - - + + #endregion - + /// /// Gets a representation of the instance @@ -123,16 +122,24 @@ public static void ResetTimeProvider() /// /// Returns a representation of the instance /// - /// A representation of the instance public DateTime DateTime => rawEpoch.ToDateTime(); - + /// /// Returns a representation of the instance /// - /// A representation of the instance public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); + /// + /// Returns a representation of the instance + /// + public DateOnly DateOnly => DateOnly.FromDateTime(rawEpoch.ToDateTime()); + + /// + /// Returns a representation of the instance + /// + public TimeOnly TimeOnly => TimeOnly.FromDateTime(rawEpoch.ToDateTime()); + #region Epoch manipulation /// @@ -149,9 +156,9 @@ public EpochTime Add(TimeSpan span) rawEpoch = newSpan.ToEpochTimestamp(); return this; } - + #endregion - + #region Operators public static EpochTime operator +(EpochTime operand1, EpochTime operand2) @@ -162,19 +169,19 @@ public EpochTime Add(TimeSpan span) { throw new EpochTimeValueException(epochSum); } - + return new EpochTime(Convert.ToInt32(epochSum)); } public static EpochTime operator -(EpochTime operand1, EpochTime operand2) { - var epochSub = operand1.Epoch - (long) operand2.Epoch; + var epochSub = operand1.Epoch - (long)operand2.Epoch; if (!epochSub.IsValidEpochTimestamp()) { throw new EpochTimeValueException(epochSub); } - + return new EpochTime(operand1.Epoch - operand2.Epoch); } #endregion diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index a2871af..41f8307 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -11,11 +11,12 @@ public sealed class LongEpochTime static LongEpochTime() { - timeProvider = new DefaultTimeProvider(); + timeProvider = new DefaultTimeProvider(); } - - #region Constructors - + + public static LongEpochTime Default => new(0); + + /// /// Initializes a new instance of /// @@ -84,12 +85,8 @@ public LongEpochTime(EpochTime epochTime) rawEpoch = epochTime.Epoch.ToLongEpochTimestamp(); } - - #endregion private long rawEpoch { get; set; } - - #region Static methods /// /// Injects a new global thread safe instance to be used globally @@ -116,10 +113,7 @@ public static void ResetTimeProvider() /// public static LongEpochTime Now => timeProvider.UtcNow.ToLongEpochTime(); - #endregion - - #region Public methods - + /// /// Gets a millisecond unix epoch representation of the instance /// @@ -145,33 +139,36 @@ public static void ResetTimeProvider() /// public LongEpochTime Add(TimeSpan timeSpan) { - var newSpan = TimeSpan + timeSpan; + TimeSpan newSpan = TimeSpan + timeSpan; rawEpoch = newSpan.ToLongEpochTimestamp(); return this; } - #endregion - - #region Operators + /// + /// Applies the given offset to the instance + /// + /// + /// + public LongEpochTime Add(TimeOnly time) + { + return this; + } public static LongEpochTime operator +(LongEpochTime operator1, LongEpochTime operator2) { // todo: There is a open issue with long number overflow - + return new LongEpochTime(operator1.Epoch + operator2.Epoch); } + public static LongEpochTime operator -(LongEpochTime operator1, LongEpochTime operator2) { //todo: There is a open issue with long number underflow - + return new LongEpochTime(operator1.Epoch - operator2.Epoch); } - - #endregion - - #region Overriden methods - + /// public override int GetHashCode() { @@ -181,12 +178,7 @@ public override int GetHashCode() /// public override bool Equals(object obj) { - if (obj is LongEpochTime comparedEpoch) - { - return comparedEpoch.Epoch == Epoch; - } - - return false; + return obj is LongEpochTime comparedEpoch && comparedEpoch.Epoch == Epoch; } /// @@ -194,6 +186,4 @@ public override string ToString() { return Epoch.ToString(); } - - #endregion } \ No newline at end of file diff --git a/Epoch.net/TimeOnlyExtensions.cs b/Epoch.net/TimeOnlyExtensions.cs new file mode 100644 index 0000000..4b5321e --- /dev/null +++ b/Epoch.net/TimeOnlyExtensions.cs @@ -0,0 +1,17 @@ +using System; + +namespace Epoch.net +{ + /// + /// Implemens utility methods on the structure + /// + public static class TimeOnlyExtensions + { + public static LongEpochTime ToEpochTime(this TimeOnly time) + { + var foo = LongEpochTime.Default; + + return foo; + } + } +} From da25f2fb89ba86025f815bfa519b201d852cd535 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 11 Nov 2023 19:21:31 +0100 Subject: [PATCH 09/14] Multiversion nuget package created --- .editorconfig | 286 +++++++++++++------ .github/workflows/dotnet.yml | 1 - Epoch.net.Test/DateOnlyExtensionsFitxture.cs | 93 +++--- Epoch.net.Test/Epoch.net.Test.csproj | 2 +- Epoch.net/Constants.cs | 6 +- Epoch.net/DateOnlyExtensions.cs | 73 +++-- Epoch.net/Epoch.net.csproj | 2 +- Epoch.net/EpochTime.cs | 3 + Epoch.net/LongEpochTime.cs | 48 +--- Epoch.net/TimeOnlyExtensions.cs | 22 +- 10 files changed, 308 insertions(+), 228 deletions(-) diff --git a/.editorconfig b/.editorconfig index b9711d7..d800b05 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,192 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true:silent +dotnet_style_collection_initializer = true:silent +dotnet_style_explicit_tuple_names = true:silent +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true:silent +dotnet_style_object_initializer = true:silent +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true:silent +dotnet_style_prefer_inferred_tuple_names = true:silent +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +dotnet_style_prefer_simplified_boolean_expressions = true:silent +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:silent + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = true +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = true + +# Expression-bodied members +csharp_style_expression_bodied_accessors = when_on_single_line +csharp_style_expression_bodied_constructors = true +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = true +csharp_style_expression_bodied_methods = true +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = when_on_single_line + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:silent +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true:silent +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true:silent + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:silent + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true:silent +csharp_style_namespace_declarations = file_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true:silent +csharp_style_implicit_object_creation_when_type_is_apparent = true:silent +csharp_style_inlined_variable_declaration = true:silent +csharp_style_prefer_index_operator = true:silent +csharp_style_prefer_local_over_anonymous_function = true:silent +csharp_style_prefer_null_check_over_type_check = true:silent +csharp_style_prefer_range_operator = true:silent +csharp_style_prefer_tuple_swap = true:silent +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true:silent +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_embedded_statements_on_same_line_experimental = false + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false -[*.{cs,vb}] #### Naming styles #### # Naming rules @@ -32,101 +219,12 @@ dotnet_naming_symbols.non_field_members.required_modifiers = # Naming styles -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = -dotnet_naming_style.begins_with_i.capitalization = pascal_case - -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case -dotnet_style_operator_placement_when_wrapping = beginning_of_line -tab_width = 4 -indent_size = 4 -end_of_line = crlf -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion -dotnet_style_prefer_auto_properties = true:silent -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:silent -dotnet_style_prefer_conditional_expression_over_return = true:silent -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion -dotnet_style_prefer_compound_assignment = true:suggestion -dotnet_style_prefer_simplified_interpolation = true:suggestion -dotnet_style_namespace_match_folder = true:suggestion -dotnet_style_readonly_field = true:suggestion -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_allow_multiple_blank_lines_experimental = true:silent -dotnet_style_allow_statement_immediately_after_block_experimental = true:silent -dotnet_code_quality_unused_parameters = all:suggestion -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_property = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_event = false:silent -[*.cs] -csharp_indent_labels = one_less_than_current -csharp_using_directive_placement = outside_namespace:silent -csharp_prefer_simple_using_statement = true:suggestion -csharp_prefer_braces = true:silent -csharp_style_namespace_declarations = block_scoped:silent -csharp_style_prefer_method_group_conversion = true:silent -csharp_style_prefer_top_level_statements = true:silent -csharp_style_prefer_primary_constructors = true:suggestion -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_accessors = true:silent -csharp_style_expression_bodied_lambdas = true:silent -csharp_style_expression_bodied_local_functions = false:silent -csharp_style_throw_expression = true:suggestion -csharp_style_prefer_null_check_over_type_check = true:suggestion -csharp_prefer_simple_default_expression = true:suggestion -csharp_style_prefer_local_over_anonymous_function = true:suggestion -csharp_style_prefer_index_operator = true:suggestion -csharp_style_prefer_range_operator = true:suggestion -csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion -csharp_style_prefer_tuple_swap = true:suggestion -csharp_style_prefer_utf8_string_literals = true:suggestion -csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:suggestion -csharp_prefer_static_local_function = true:suggestion -csharp_style_prefer_readonly_struct = true:suggestion -csharp_style_prefer_readonly_struct_member = true:suggestion -csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent -csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent -csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent -csharp_style_conditional_delegate_call = true:suggestion -csharp_style_prefer_switch_expression = true:suggestion -csharp_style_prefer_pattern_matching = true:silent -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -csharp_style_prefer_not_pattern = true:suggestion -csharp_style_prefer_extended_property_pattern = true:suggestion -csharp_style_var_for_built_in_types = false:silent -csharp_style_var_when_type_is_apparent = false:silent -csharp_style_var_elsewhere = false:silent -csharp_space_around_binary_operators = before_and_after \ No newline at end of file +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index de7fc43..1464e17 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -20,7 +20,6 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 8.0.x 7.0.x 6.0.x - name: Restore dependencies diff --git a/Epoch.net.Test/DateOnlyExtensionsFitxture.cs b/Epoch.net.Test/DateOnlyExtensionsFitxture.cs index 7bb8b19..05e9fc3 100644 --- a/Epoch.net.Test/DateOnlyExtensionsFitxture.cs +++ b/Epoch.net.Test/DateOnlyExtensionsFitxture.cs @@ -2,53 +2,54 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; -namespace Epoch.net.Test +#if NET6_0_OR_GREATER +namespace Epoch.net.Test; + +[TestClass] +public class DateOnlyExtensionsFitxture { - [TestClass] - public class DateOnlyExtensionsFitxture + private readonly DateOnly After1970_UTC = DateOnly.FromDateTime(TestConstants.After1970_UTC); + private readonly DateOnly Before1970_UTC = DateOnly.FromDateTime(TestConstants.Before1970_UTC); + private readonly DateOnly After1970 = DateOnly.FromDateTime(TestConstants.After1970); + private readonly DateOnly Before1970 = DateOnly.FromDateTime(TestConstants.Before1970); + private readonly DateOnly OutOfBounds = DateOnly.FromDateTime(TestConstants.OutOfBounds); + private readonly TimeOnly RandomTime = new(16, 23, 12); + private readonly int RandomTimeOffset = 58992; + + [TestMethod] + public void ToEpoch_UTC() + { + _ = After1970_UTC.ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); + _ = Before1970_UTC.ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); + } + + [TestMethod] + public void ToEpoch() + { + _ = After1970.ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); + _ = Before1970.ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); + } + + [TestMethod] + public void ToEpoch_OutOfBounds() + { + var act = () => OutOfBounds.ToEpochTime().Epoch; + + _ = act.Should().Throw(); + } + + [TestMethod] + public void ToEpoch_WithTime_UTC() + { + _ = After1970_UTC.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp + RandomTimeOffset); + _ = Before1970_UTC.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp + RandomTimeOffset); + } + + [TestMethod] + public void ToEpoch_WithTime() { - private readonly DateOnly After1970_UTC = DateOnly.FromDateTime(TestConstants.After1970_UTC); - private readonly DateOnly Before1970_UTC = DateOnly.FromDateTime(TestConstants.Before1970_UTC); - private readonly DateOnly After1970 = DateOnly.FromDateTime(TestConstants.After1970); - private readonly DateOnly Before1970 = DateOnly.FromDateTime(TestConstants.Before1970); - private readonly DateOnly OutOfBounds = DateOnly.FromDateTime(TestConstants.OutOfBounds); - private readonly TimeOnly RandomTime = new(16, 23, 12); - private readonly int RandomTimeOffset = 58992; - - [TestMethod] - public void ToEpoch_UTC() - { - After1970_UTC.ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); - Before1970_UTC.ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); - } - - [TestMethod] - public void ToEpoch() - { - After1970.ToEpochTime().Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp); - Before1970.ToEpochTime().Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp); - } - - [TestMethod] - public void ToEpoch_OutOfBounds() - { - var act = () => OutOfBounds.ToEpochTime().Epoch; - - act.Should().Throw(); - } - - [TestMethod] - public void ToEpoch_WithTime_UTC() - { - After1970_UTC.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp + RandomTimeOffset); - Before1970_UTC.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp + RandomTimeOffset); - } - - [TestMethod] - public void ToEpoch_WithTime() - { - After1970.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp + RandomTimeOffset); - Before1970.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp + RandomTimeOffset); - } + _ = After1970.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.After1970_UTC_Timestamp + RandomTimeOffset); + _ = Before1970.ToEpochTime(RandomTime).Epoch.Should().Be(TestConstants.Before1970_UTC_Timestamp + RandomTimeOffset); } } +#endif \ No newline at end of file diff --git a/Epoch.net.Test/Epoch.net.Test.csproj b/Epoch.net.Test/Epoch.net.Test.csproj index 89a901c..9588544 100644 --- a/Epoch.net.Test/Epoch.net.Test.csproj +++ b/Epoch.net.Test/Epoch.net.Test.csproj @@ -1,7 +1,7 @@  - net7.0;net6.0 + net7.0;net6.0;net48 false diff --git a/Epoch.net/Constants.cs b/Epoch.net/Constants.cs index 55e74ec..a3287d1 100644 --- a/Epoch.net/Constants.cs +++ b/Epoch.net/Constants.cs @@ -4,11 +4,11 @@ namespace Epoch.net; public static class Constants { - public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + public static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); public const int MIN_VALUE_INT = -2147483648; public const int MAX_VALUE_INT = 2147483647; - public static readonly DateTime MAX_VALUE_DATETIME = new DateTime(2038, 1, 19,3,14,07, DateTimeKind.Utc); // 3:14:07 Tuesday, 19 January 2038 UTC - public static readonly DateTime MIN_VALUE_DATETIME = new DateTime(1901, 12, 13, 20, 45, 52, DateTimeKind.Utc); // 20:45:52 Friday, 13 December 1901 UTC + public static readonly DateTime MAX_VALUE_DATETIME = new(2038, 1, 19,3,14,07, DateTimeKind.Utc); // 3:14:07 Tuesday, 19 January 2038 UTC + public static readonly DateTime MIN_VALUE_DATETIME = new(1901, 12, 13, 20, 45, 52, DateTimeKind.Utc); // 20:45:52 Friday, 13 December 1901 UTC public const long MAX_VALUE_LONG = 922337203685477; public const long MIN_VALUE_LONG = -922337203685477; } \ No newline at end of file diff --git a/Epoch.net/DateOnlyExtensions.cs b/Epoch.net/DateOnlyExtensions.cs index 32ce610..50fe03e 100644 --- a/Epoch.net/DateOnlyExtensions.cs +++ b/Epoch.net/DateOnlyExtensions.cs @@ -1,43 +1,40 @@ using System; -namespace Epoch.net +namespace Epoch.net; +#if NET6_0_OR_GREATER +public static class DateOnlyExtensions { - public static class DateOnlyExtensions - { - /// - /// Transforms the given structure into a - /// - /// The structure to convert into the - /// - /// A new instance of representaiton of the given structure - /// - /// - /// If the exceeded the valid range of a Unix Epoch - /// - public static EpochTime ToEpochTime(this DateOnly date) => date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc).ToEpochTime(); + /// + /// Transforms the given structure into a + /// + /// The structure to convert into the + /// + /// A new instance of representaiton of the given structure + /// + /// + /// If the exceeded the valid range of a Unix Epoch + /// + public static EpochTime ToEpochTime(this DateOnly date) => date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc).ToEpochTime(); - /// - /// Transforms the given structure into a with the given offset - /// - /// The structure to convert into the - /// The structure used for the time ofdfset from midnight - /// Determines if the given is UTC or local time. TRUE => UTC, FALSE => Local time - /// - /// It is assumed that the is UTC time. Determined by the - /// - /// - /// A new instance of representaiton of the given and structure - /// - /// - /// If the exceeded the valid range of a Unix Epoch - /// - public static EpochTime ToEpochTime(this DateOnly date, TimeOnly time, bool isUtcTime = true) - { - return isUtcTime switch - { - true => date.ToDateTime(time, DateTimeKind.Utc).ToEpochTime(), - false => date.ToDateTime(time, DateTimeKind.Local).ToEpochTime() - }; - } - } + /// + /// Transforms the given structure into a with the given offset + /// + /// The structure to convert into the + /// The structure used for the time ofdfset from midnight + /// Determines if the given is UTC or local time. TRUE => UTC, FALSE => Local time + /// + /// It is assumed that the is UTC time. Determined by the + /// + /// + /// A new instance of representaiton of the given and structure + /// + /// + /// If the exceeded the valid range of a Unix Epoch + /// + public static EpochTime ToEpochTime(this DateOnly date, TimeOnly time, bool isUtcTime = true) => isUtcTime switch + { + true => date.ToDateTime(time, DateTimeKind.Utc).ToEpochTime(), + false => date.ToDateTime(time, DateTimeKind.Local).ToEpochTime() + }; } +#endif diff --git a/Epoch.net/Epoch.net.csproj b/Epoch.net/Epoch.net.csproj index 15111bc..5977403 100644 --- a/Epoch.net/Epoch.net.csproj +++ b/Epoch.net/Epoch.net.csproj @@ -11,7 +11,7 @@ Implements a simple set of helpers to handle EPOCH timestamps in .NET - net7.0;net6.0 + net7.0;net6.0;net48 diff --git a/Epoch.net/EpochTime.cs b/Epoch.net/EpochTime.cs index 9955f75..89967b5 100644 --- a/Epoch.net/EpochTime.cs +++ b/Epoch.net/EpochTime.cs @@ -130,6 +130,7 @@ public static void ResetTimeProvider() /// public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); +#if NET6_0_OR_GREATER /// /// Returns a representation of the instance /// @@ -140,6 +141,8 @@ public static void ResetTimeProvider() /// public TimeOnly TimeOnly => TimeOnly.FromDateTime(rawEpoch.ToDateTime()); +#endif + #region Epoch manipulation /// diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index 41f8307..ad4f1c5 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -9,31 +9,21 @@ public sealed class LongEpochTime { private static IDateTimeProvider timeProvider; - static LongEpochTime() - { - timeProvider = new DefaultTimeProvider(); - } + static LongEpochTime() => timeProvider = new DefaultTimeProvider(); public static LongEpochTime Default => new(0); - /// /// Initializes a new instance of /// /// The from which to initialize the instance - public LongEpochTime(DateTime dateTime) - { - rawEpoch = dateTime.ToLongEpochTimestamp(); - } + public LongEpochTime(DateTime dateTime) => rawEpoch = dateTime.ToLongEpochTimestamp(); /// /// Initializes a new instance of /// /// The number of milliseconds since 1970-01-01T00:00Z - public LongEpochTime(long longEpochTimestamp) - { - rawEpoch = longEpochTimestamp; - } + public LongEpochTime(long longEpochTimestamp) => rawEpoch = longEpochTimestamp; /// /// Initializes a new instance of @@ -103,17 +93,13 @@ public static void SetTimeProvider(IDateTimeProvider timeProvider) /// /// Resets the global time provider to the default system time provider /// - public static void ResetTimeProvider() - { - timeProvider = new DefaultTimeProvider(); - } + public static void ResetTimeProvider() => timeProvider = new DefaultTimeProvider(); /// /// Gets the current UTC date and time as an /// public static LongEpochTime Now => timeProvider.UtcNow.ToLongEpochTime(); - /// /// Gets a millisecond unix epoch representation of the instance /// @@ -139,20 +125,19 @@ public static void ResetTimeProvider() /// public LongEpochTime Add(TimeSpan timeSpan) { - TimeSpan newSpan = TimeSpan + timeSpan; + var newSpan = TimeSpan + timeSpan; rawEpoch = newSpan.ToLongEpochTimestamp(); return this; } +#if NET6_0_OR_GREATER /// /// Applies the given offset to the instance /// /// /// - public LongEpochTime Add(TimeOnly time) - { - return this; - } + public LongEpochTime Add(TimeOnly time) => this; +#endif public static LongEpochTime operator +(LongEpochTime operator1, LongEpochTime operator2) { @@ -161,7 +146,7 @@ public LongEpochTime Add(TimeOnly time) return new LongEpochTime(operator1.Epoch + operator2.Epoch); } - + public static LongEpochTime operator -(LongEpochTime operator1, LongEpochTime operator2) { //todo: There is a open issue with long number underflow @@ -170,20 +155,11 @@ public LongEpochTime Add(TimeOnly time) } /// - public override int GetHashCode() - { - return rawEpoch.GetHashCode(); - } + public override int GetHashCode() => rawEpoch.GetHashCode(); /// - public override bool Equals(object obj) - { - return obj is LongEpochTime comparedEpoch && comparedEpoch.Epoch == Epoch; - } + public override bool Equals(object obj) => obj is LongEpochTime comparedEpoch && comparedEpoch.Epoch == Epoch; /// - public override string ToString() - { - return Epoch.ToString(); - } + public override string ToString() => Epoch.ToString(); } \ No newline at end of file diff --git a/Epoch.net/TimeOnlyExtensions.cs b/Epoch.net/TimeOnlyExtensions.cs index 4b5321e..6456709 100644 --- a/Epoch.net/TimeOnlyExtensions.cs +++ b/Epoch.net/TimeOnlyExtensions.cs @@ -1,17 +1,23 @@ using System; -namespace Epoch.net +namespace Epoch.net; + +#if NET6_0_OR_GREATER +/// +/// Implemens utility methods on the structure +/// +public static class TimeOnlyExtensions { /// - /// Implemens utility methods on the structure + /// /// - public static class TimeOnlyExtensions + /// + /// + public static LongEpochTime ToEpochTime(this TimeOnly time) { - public static LongEpochTime ToEpochTime(this TimeOnly time) - { - var foo = LongEpochTime.Default; + var foo = LongEpochTime.Default; - return foo; - } + return foo; } } +#endif From 7c4ca59364b1a805354a12a26e7b8dacabb906fb Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 11 Nov 2023 21:01:15 +0100 Subject: [PATCH 10/14] Removed the shared Constants class --- CHANGELOG.md | 8 ++- Epoch.net.Test/EpochTime_Ctor_Fixture.cs | 18 ++++--- Epoch.net.Test/EpochTime_Operators_Fixture.cs | 6 +-- Epoch.net.Test/IntExtensionsFixture.cs | 4 +- Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs | 8 +-- Epoch.net.Test/LongExtensionsFixture.cs | 8 +-- Epoch.net/Constants.cs | 14 ----- Epoch.net/DateTimeExtensions.cs | 6 +-- Epoch.net/EpochTime.cs | 54 ++++++++++++++++++- Epoch.net/EpochTimeValueException.cs | 50 +++++++++++++---- Epoch.net/IntExtensions.cs | 2 +- Epoch.net/LongEpochTime.cs | 14 +++++ Epoch.net/LongEpochTimeValueException.cs | 10 ++++ Epoch.net/LongExtensions.cs | 6 +-- Epoch.net/TimeSpanExtensions.cs | 4 +- 15 files changed, 153 insertions(+), 59 deletions(-) delete mode 100644 Epoch.net/Constants.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 86ba106..2f2046c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,18 +4,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [3.2] +## [4.0] ### Changed - Updated to .net version 7 - Moved build to github actions -- +- Updated code formatting to new standard ### Added - DateOnly extensions - TimeOnly extensions +### Removed + +- The Constants static class + ## [3.1] ### Added diff --git a/Epoch.net.Test/EpochTime_Ctor_Fixture.cs b/Epoch.net.Test/EpochTime_Ctor_Fixture.cs index 6053efc..89c245a 100644 --- a/Epoch.net.Test/EpochTime_Ctor_Fixture.cs +++ b/Epoch.net.Test/EpochTime_Ctor_Fixture.cs @@ -15,26 +15,30 @@ public void Int() { Assert.AreEqual(0, new EpochTime(0).Epoch); - Assert.AreEqual(Constants.MAX_VALUE_INT, new EpochTime(Constants.MAX_VALUE_INT).Epoch); - Assert.AreEqual(Constants.MIN_VALUE_INT, new EpochTime(Constants.MIN_VALUE_INT).Epoch); + Assert.AreEqual(EpochTime.MAX_VALUE, EpochTime.MAX.Epoch); + Assert.AreEqual(EpochTime.MIN_VALUE, EpochTime.MIN.Epoch); + + Assert.AreEqual(EpochTime.MIN, new EpochTime(EpochTime.MIN_VALUE)); + Assert.AreEqual(EpochTime.MAX, new EpochTime(EpochTime.MAX_VALUE)); } [TestMethod] public void DateTime() { Assert.AreEqual(0, new EpochTime(0).Epoch); + Assert.AreEqual(0, EpochTime.Default.Epoch); Assert.AreEqual(ValidEpochTimestamp, new EpochTime(ValidDateTime).Epoch); - Assert.AreEqual(Constants.MIN_VALUE_INT, new EpochTime(Constants.MIN_VALUE_DATETIME).Epoch); - Assert.AreEqual(Constants.MAX_VALUE_INT, new EpochTime(Constants.MAX_VALUE_DATETIME).Epoch); + Assert.AreEqual(EpochTime.MIN, new EpochTime(EpochTime.MIN_DATETIME)); + Assert.AreEqual(EpochTime.MAX, new EpochTime(EpochTime.MAX_DATETIME)); Assert.ThrowsException(() => - new EpochTime(Constants.MAX_VALUE_DATETIME.AddSeconds(1))); + new EpochTime(EpochTime.MAX_DATETIME.AddSeconds(1))); Assert.ThrowsException(() => - new EpochTime(Constants.MIN_VALUE_DATETIME.AddSeconds(-1))); + new EpochTime(EpochTime.MIN_DATETIME.AddSeconds(-1))); } [TestMethod] - public void EpochTime() + public void EpochTime_Test() { Assert.AreEqual(ValidEpochTimestamp, new EpochTime(ValidEpochTime).Epoch); diff --git a/Epoch.net.Test/EpochTime_Operators_Fixture.cs b/Epoch.net.Test/EpochTime_Operators_Fixture.cs index be28e53..000dddb 100644 --- a/Epoch.net.Test/EpochTime_Operators_Fixture.cs +++ b/Epoch.net.Test/EpochTime_Operators_Fixture.cs @@ -7,8 +7,6 @@ namespace Epoch.net.Test public class EpochTime_Operators_Fixture { private readonly EpochTime Valid_EpochTime = new EpochTime(500); - private readonly EpochTime Max_EpochTime = new EpochTime(Constants.MAX_VALUE_INT); - private readonly EpochTime Min_EpochTime = new EpochTime(Constants.MIN_VALUE_INT); [TestMethod] public void Addition() @@ -16,7 +14,7 @@ public void Addition() Assert.AreEqual(1000.ToEpochTime(), Valid_EpochTime + Valid_EpochTime); // Adding over the integer range throws an Exception - Assert.ThrowsException(() => Max_EpochTime + Valid_EpochTime); + Assert.ThrowsException(() => EpochTime.MAX + Valid_EpochTime); } [TestMethod] @@ -25,7 +23,7 @@ public void Substration() Assert.AreEqual(Valid_EpochTime, 1000.ToEpochTime() - Valid_EpochTime); // Subtracting over the integer range throws an Exception - Assert.ThrowsException(() => Min_EpochTime - Valid_EpochTime); + Assert.ThrowsException(() => EpochTime.MIN - Valid_EpochTime); } } } \ No newline at end of file diff --git a/Epoch.net.Test/IntExtensionsFixture.cs b/Epoch.net.Test/IntExtensionsFixture.cs index 98c433f..3a5702a 100644 --- a/Epoch.net.Test/IntExtensionsFixture.cs +++ b/Epoch.net.Test/IntExtensionsFixture.cs @@ -19,8 +19,8 @@ public void ToDateTime() Assert.AreEqual(After_1970_DateTime, After_1970_EpochTimestamp.ToDateTime()); Assert.AreEqual(Before_1970_DateTime, Before_1970_EpochTimestamp.ToDateTime()); - Assert.AreEqual(Constants.MAX_VALUE_DATETIME, Constants.MAX_VALUE_INT.ToDateTime()); - Assert.AreEqual(Constants.MIN_VALUE_DATETIME, Constants.MIN_VALUE_INT.ToDateTime()); + Assert.AreEqual(EpochTime.MAX_DATETIME, EpochTime.MAX_VALUE.ToDateTime()); + Assert.AreEqual(EpochTime.MIN_DATETIME, EpochTime.MIN_VALUE.ToDateTime()); } [TestMethod] diff --git a/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs b/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs index 6f56739..171c900 100644 --- a/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs +++ b/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs @@ -26,20 +26,20 @@ public void TimeSpan() Assert.AreEqual(ValidLongEpochTimestamp, new LongEpochTime(System.TimeSpan.FromMilliseconds(ValidLongEpochTimestamp)).Epoch); - Assert.AreEqual(Constants.MAX_VALUE_LONG, new LongEpochTime(System.TimeSpan.MaxValue).Epoch); - Assert.AreEqual(Constants.MIN_VALUE_LONG, new LongEpochTime(System.TimeSpan.MinValue).Epoch); + Assert.AreEqual(LongEpochTime.MAX, new LongEpochTime(System.TimeSpan.MaxValue)); + Assert.AreEqual(LongEpochTime.MIN, new LongEpochTime(System.TimeSpan.MinValue)); } [TestMethod] public void DateTime() { - Assert.AreEqual(0L, new LongEpochTime(Constants.UnixEpoch).Epoch); + Assert.AreEqual(0L, LongEpochTime.Default.Epoch); Assert.AreEqual(ValidLongEpochTimestamp, new LongEpochTime(ValidDateTime).Epoch); } [TestMethod] - public void LongEpochTime() + public void LongEpochTimeTest() { Assert.AreEqual(ValidLongEpochTimestamp, new LongEpochTime(ValidLongEpochTime).Epoch); } diff --git a/Epoch.net.Test/LongExtensionsFixture.cs b/Epoch.net.Test/LongExtensionsFixture.cs index ff78712..efdb0b6 100644 --- a/Epoch.net.Test/LongExtensionsFixture.cs +++ b/Epoch.net.Test/LongExtensionsFixture.cs @@ -26,7 +26,7 @@ public void IsValidEpochTimestamp() [TestMethod] public void ToDateTime() { - Assert.AreEqual(Constants.UnixEpoch, 0L.ToDateTime()); + Assert.AreEqual(LongEpochTime.DefaultDateTime, 0L.ToDateTime()); Assert.AreEqual(PositiveDateTime, PositiveLongEpochTimestamp.ToDateTime()); Assert.AreEqual(NegativeDateTime, NegativeLongEpochTimestamp.ToDateTime()); @@ -46,12 +46,12 @@ public void ToEpochTimestamp() { Assert.AreEqual(0, 0L.ToEpochTimestamp()); - Assert.AreEqual(Constants.MAX_VALUE_INT, ((long)Constants.MAX_VALUE_INT * 1000).ToEpochTimestamp()); - Assert.AreEqual(Constants.MIN_VALUE_INT, ((long)Constants.MIN_VALUE_INT * 1000).ToEpochTimestamp()); + Assert.AreEqual(EpochTime.MAX_VALUE, ((long) EpochTime.MAX_VALUE * 1000).ToEpochTimestamp()); + Assert.AreEqual(EpochTime.MIN_VALUE, ((long)EpochTime.MIN_VALUE * 1000).ToEpochTimestamp()); Assert.AreEqual(PositiveDateTime.ToEpochTimestamp(), PositiveLongEpochTimestamp.ToEpochTimestamp()); - Assert.ThrowsException(() => ((long)Constants.MIN_VALUE_INT * 1000 - 1000).ToEpochTimestamp()); + Assert.ThrowsException(() => ((long)EpochTime.MIN_VALUE * 1000 - 1000).ToEpochTimestamp()); } } } \ No newline at end of file diff --git a/Epoch.net/Constants.cs b/Epoch.net/Constants.cs deleted file mode 100644 index a3287d1..0000000 --- a/Epoch.net/Constants.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Epoch.net; - -public static class Constants -{ - public static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - public const int MIN_VALUE_INT = -2147483648; - public const int MAX_VALUE_INT = 2147483647; - public static readonly DateTime MAX_VALUE_DATETIME = new(2038, 1, 19,3,14,07, DateTimeKind.Utc); // 3:14:07 Tuesday, 19 January 2038 UTC - public static readonly DateTime MIN_VALUE_DATETIME = new(1901, 12, 13, 20, 45, 52, DateTimeKind.Utc); // 20:45:52 Friday, 13 December 1901 UTC - public const long MAX_VALUE_LONG = 922337203685477; - public const long MIN_VALUE_LONG = -922337203685477; -} \ No newline at end of file diff --git a/Epoch.net/DateTimeExtensions.cs b/Epoch.net/DateTimeExtensions.cs index 998f37c..25a14f8 100644 --- a/Epoch.net/DateTimeExtensions.cs +++ b/Epoch.net/DateTimeExtensions.cs @@ -15,7 +15,7 @@ public static class DateTimeExtensions /// The LongEpochTimestamp is the number of milliseconds since 1970-01-01T00:00Z public static long ToLongEpochTimestamp(this DateTime dateTime) { - var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - Constants.UnixEpoch; + var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - LongEpochTime.DefaultDateTime; return Convert.ToInt64(timeSinceDisco.TotalMilliseconds); } @@ -36,7 +36,7 @@ public static int ToEpochTimestamp(this DateTime dateTime) throw new EpochTimeValueException(dateTime); } - var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - Constants.UnixEpoch; + var timeSinceDisco = TimeZoneInfo.ConvertTimeToUtc(dateTime.ToUniversalTime()) - LongEpochTime.DefaultDateTime; return Convert.ToInt32(timeSinceDisco.TotalSeconds); } @@ -76,6 +76,6 @@ public static LongEpochTime ToLongEpochTime(this DateTime dateTime) /// True if the is in a valid range, False if not public static bool IsValidEpochTime(this DateTime dateTime) { - return dateTime >= Constants.MIN_VALUE_DATETIME && dateTime <= Constants.MAX_VALUE_DATETIME; + return dateTime >= EpochTime.MIN_DATETIME && dateTime <= EpochTime.MAX_DATETIME; } } \ No newline at end of file diff --git a/Epoch.net/EpochTime.cs b/Epoch.net/EpochTime.cs index 89967b5..ae18ddc 100644 --- a/Epoch.net/EpochTime.cs +++ b/Epoch.net/EpochTime.cs @@ -12,6 +12,39 @@ static EpochTime() TimeProvider = new DefaultTimeProvider(); } + /// + /// Provides a new instance of a with the maximal possible value + /// + public static EpochTime MAX => new EpochTime(MAX_VALUE); + /// + /// Provides a new instance of a with the minimal possible value + /// + public static EpochTime MIN => new EpochTime(MIN_VALUE); + /// + /// The minimal raw epoch value + /// + public const int MIN_VALUE = -2147483648; + /// + /// The maximal raw epoch value + /// + public const int MAX_VALUE = 2147483647; + /// + /// The maximal value that a can take + /// + public static readonly DateTime MAX_DATETIME = new(2038, 1, 19,3,14,07, DateTimeKind.Utc); // 3:14:07 Tuesday, 19 January 2038 UTC + /// + /// The minimal value that a can take + /// + public static readonly DateTime MIN_DATETIME = new(1901, 12, 13, 20, 45, 52, DateTimeKind.Utc); // 20:45:52 Friday, 13 December 1901 UTC + + /// + /// The default value of + /// + /// + /// Thursday, January 1, 1970 12:00:00 AM GMT + /// + public static EpochTime Default => new(0); + private static IDateTimeProvider TimeProvider { get; set; } #region Constructors @@ -164,11 +197,20 @@ public EpochTime Add(TimeSpan span) #region Operators + /// + /// Implements the + operator between two instances + /// + /// The augend + /// The addend + /// The sum of the two + /// + /// If the result is not a valid + /// public static EpochTime operator +(EpochTime operand1, EpochTime operand2) { var epochSum = operand1.Epoch + (long)operand2.Epoch; - if (!epochSum.IsValidEpochTimestamp()) + if (epochSum.IsValidEpochTimestamp() is false) { throw new EpochTimeValueException(epochSum); } @@ -176,11 +218,19 @@ public EpochTime Add(TimeSpan span) return new EpochTime(Convert.ToInt32(epochSum)); } + /// + /// Implements the - operator between two instances + /// + /// The minuend + /// The subtrahend + /// The Difference between the two instances + /// + /// If the result is not a valid public static EpochTime operator -(EpochTime operand1, EpochTime operand2) { var epochSub = operand1.Epoch - (long)operand2.Epoch; - if (!epochSub.IsValidEpochTimestamp()) + if (epochSub.IsValidEpochTimestamp() is false) { throw new EpochTimeValueException(epochSub); } diff --git a/Epoch.net/EpochTimeValueException.cs b/Epoch.net/EpochTimeValueException.cs index 1736a88..bfbe8ac 100644 --- a/Epoch.net/EpochTimeValueException.cs +++ b/Epoch.net/EpochTimeValueException.cs @@ -2,6 +2,9 @@ namespace Epoch.net; +/// +/// Denotes the error state of a +/// public class EpochTimeValueException : Exception { private const string DefaultErrorMessage = "The provided value could not be represented in a Epoch"; @@ -9,22 +12,47 @@ public class EpochTimeValueException : Exception private const string TimeStampErrorMessage = "The Timespan {0} is not in a Epoch range"; private const string EpochTimeErrorMessage = "The EpochTime {0} is not in a Epoch range"; private const string LongErrorMessage = "The number {0} is not in a Epoch range"; - + + /// + /// Creates a new instance of the + /// public EpochTimeValueException() - : base(DefaultErrorMessage){} - + : base(DefaultErrorMessage) { } + + /// + /// Creates a new instance of the with the given error message + /// + /// The Error message to assigne to the new instance of the public EpochTimeValueException(string message) - :base(message) {} - + : base(message) { } + + /// + /// Creates a new instance of the with a given + /// + /// The that is not in a valid Epoch range + /// + /// It is assumed that the provided is not in a valid Epoch range. + /// public EpochTimeValueException(DateTime value) - :base(string.Format(DateTimeErrorMessage, value)){} + : base(string.Format(DateTimeErrorMessage, value)) { } + /// + /// Creates a new instance of the with a given + /// + /// The that is not in a valid Epoch range + /// + /// It is assumed that the is not in a valid Epoch range + /// public EpochTimeValueException(TimeSpan value) - :base(string.Format(TimeStampErrorMessage, value)){} - - public EpochTimeValueException(EpochTime value) - :base(string.Format(EpochTimeErrorMessage, value)){} + : base(string.Format(TimeStampErrorMessage, value)) { } + /// + /// Creates a new instance of the with a given value + /// + /// The that is not in a valid Epoch range + /// + /// It is assumed that the value is not in a valid Epoch range + /// public EpochTimeValueException(long value) - :base(string.Format(LongErrorMessage, value)){} + : base(string.Format(LongErrorMessage, value)) { } } \ No newline at end of file diff --git a/Epoch.net/IntExtensions.cs b/Epoch.net/IntExtensions.cs index 09ab406..6c9884f 100644 --- a/Epoch.net/IntExtensions.cs +++ b/Epoch.net/IntExtensions.cs @@ -14,7 +14,7 @@ public static class IntExtensions /// A initialized to the given offset in seconds from 1970-01-01T00:00Z public static DateTime ToDateTime(this int epoch) { - return Constants.UnixEpoch.AddSeconds(epoch); + return LongEpochTime.DefaultDateTime.AddSeconds(epoch); } /// diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index ad4f1c5..598774d 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -11,8 +11,22 @@ public sealed class LongEpochTime static LongEpochTime() => timeProvider = new DefaultTimeProvider(); + /// + /// The default value of + /// + /// + /// Thursday, January 1, 1970 12:00:00 AM GMT + /// public static LongEpochTime Default => new(0); + public static DateTime DefaultDateTime => new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + public const long MAX_VALUE = 922337203685477; + public const long MIN_VALUE = -922337203685477; + + public static LongEpochTime MIN => new LongEpochTime(MIN_VALUE); + public static LongEpochTime MAX => new LongEpochTime(MAX_VALUE); + /// /// Initializes a new instance of /// diff --git a/Epoch.net/LongEpochTimeValueException.cs b/Epoch.net/LongEpochTimeValueException.cs index af0d2de..0d3e253 100644 --- a/Epoch.net/LongEpochTimeValueException.cs +++ b/Epoch.net/LongEpochTimeValueException.cs @@ -2,10 +2,20 @@ namespace Epoch.net; +/// +/// Denotes the error state of a +/// public class LongEpochTimeValueException : Exception { private const string TimeSpanErrorMessage = "The provided TimeSpan {0} does not conform to the LongEpochTime range"; + /// + /// Creates a new instance of the with the given + /// + /// The that is not inside the valid range + /// + /// It is assumed that the is not in a valid value range + /// public LongEpochTimeValueException(TimeSpan value) :base(string.Format(TimeSpanErrorMessage, value)) { diff --git a/Epoch.net/LongExtensions.cs b/Epoch.net/LongExtensions.cs index 07a42ac..62d8d51 100644 --- a/Epoch.net/LongExtensions.cs +++ b/Epoch.net/LongExtensions.cs @@ -12,11 +12,11 @@ public static class LongExtensions /// /// The LongEpochTimestamp /// - /// True if the EpochTimestamp is in a valid EpochTime range, False if not + /// True if the EpochTimestamp is in a valid range, False if not /// public static bool IsValidEpochTimestamp(this long epoch) { - return epoch >= Constants.MIN_VALUE_INT && epoch <= Constants.MAX_VALUE_INT; + return epoch >= EpochTime.MIN_VALUE && epoch <= EpochTime.MAX_VALUE; } /// @@ -26,7 +26,7 @@ public static bool IsValidEpochTimestamp(this long epoch) /// A representation of the given LongEpochTimestamp public static DateTime ToDateTime(this long value) { - return Constants.UnixEpoch.AddMilliseconds(value); + return LongEpochTime.DefaultDateTime.AddMilliseconds(value); } /// diff --git a/Epoch.net/TimeSpanExtensions.cs b/Epoch.net/TimeSpanExtensions.cs index 3317c62..b9e62b9 100644 --- a/Epoch.net/TimeSpanExtensions.cs +++ b/Epoch.net/TimeSpanExtensions.cs @@ -78,7 +78,7 @@ public static bool IsValidEpochTime(this TimeSpan timeSpan) { var totalSeconds = timeSpan.TotalSeconds; - return totalSeconds >= Constants.MIN_VALUE_INT && totalSeconds <= Constants.MAX_VALUE_INT; + return totalSeconds >= EpochTime.MIN_VALUE && totalSeconds <= EpochTime.MAX_VALUE; } /// @@ -92,6 +92,6 @@ public static bool IsValidLongEpochTime(this TimeSpan timeSpan) { var totalMilliseconds = timeSpan.TotalMilliseconds; - return totalMilliseconds >= Constants.MIN_VALUE_LONG && totalMilliseconds <= Constants.MAX_VALUE_LONG; + return totalMilliseconds >= LongEpochTime.MIN_VALUE && totalMilliseconds <= LongEpochTime.MAX_VALUE; } } \ No newline at end of file From 6ee95650db17710387f4483108061f33e92e00d9 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 11 Nov 2023 21:03:44 +0100 Subject: [PATCH 11/14] Code formatting --- Epoch.net/DefaultTimeProvider.cs | 1 + Epoch.net/EpochTime.cs | 86 +++++++----------------- Epoch.net/IntExtensions.cs | 25 ++----- Epoch.net/LongEpochTime.cs | 5 +- Epoch.net/LongEpochTimeValueException.cs | 4 +- Epoch.net/LongExtensions.cs | 29 ++------ Epoch.net/TimeSpanExtensions.cs | 36 +++------- 7 files changed, 52 insertions(+), 134 deletions(-) diff --git a/Epoch.net/DefaultTimeProvider.cs b/Epoch.net/DefaultTimeProvider.cs index b714ef7..aba779b 100644 --- a/Epoch.net/DefaultTimeProvider.cs +++ b/Epoch.net/DefaultTimeProvider.cs @@ -7,5 +7,6 @@ namespace Epoch.net; /// public class DefaultTimeProvider : IDateTimeProvider { + /// public DateTime UtcNow => DateTime.UtcNow; } \ No newline at end of file diff --git a/Epoch.net/EpochTime.cs b/Epoch.net/EpochTime.cs index ae18ddc..3057e7f 100644 --- a/Epoch.net/EpochTime.cs +++ b/Epoch.net/EpochTime.cs @@ -7,19 +7,16 @@ namespace Epoch.net; /// public sealed class EpochTime { - static EpochTime() - { - TimeProvider = new DefaultTimeProvider(); - } + static EpochTime() => TimeProvider = new DefaultTimeProvider(); /// /// Provides a new instance of a with the maximal possible value /// - public static EpochTime MAX => new EpochTime(MAX_VALUE); + public static EpochTime MAX => new(MAX_VALUE); /// /// Provides a new instance of a with the minimal possible value /// - public static EpochTime MIN => new EpochTime(MIN_VALUE); + public static EpochTime MIN => new(MIN_VALUE); /// /// The minimal raw epoch value /// @@ -53,10 +50,7 @@ static EpochTime() /// Creates a new instance of with a given rawEpoch /// /// The number of seconds from 1970-01-01T00:00:00 - public EpochTime(int rawEpoch) - { - this.rawEpoch = rawEpoch; - } + public EpochTime(int rawEpoch) => this.Epoch = rawEpoch; /// /// Creates a new instance of with the given @@ -75,7 +69,7 @@ public EpochTime(DateTime dateTime) throw new EpochTimeValueException(dateTime); } - rawEpoch = dateTime.ToEpochTimestamp(); + Epoch = dateTime.ToEpochTimestamp(); } /// @@ -93,7 +87,7 @@ public EpochTime(EpochTime epoch) throw new ArgumentNullException(nameof(epoch), "The provided epoch can not be null"); } - rawEpoch = epoch.Epoch; + Epoch = epoch.Epoch; } /// @@ -110,12 +104,10 @@ public EpochTime(TimeSpan timeSpan) throw new EpochTimeValueException(timeSpan); } - rawEpoch = timeSpan.ToEpochTimestamp(); + Epoch = timeSpan.ToEpochTimestamp(); } #endregion - private int rawEpoch; - #region Static methods /// @@ -133,46 +125,40 @@ public static void SetTimeProvider(IDateTimeProvider timeProvider) /// /// Resets the global time provider to the default system time provider /// - public static void ResetTimeProvider() - { - TimeProvider = new DefaultTimeProvider(); - } + public static void ResetTimeProvider() => TimeProvider = new DefaultTimeProvider(); /// /// Gets the current UTC date and time as an /// public static EpochTime Now => TimeProvider.UtcNow.ToEpochTime(); - #endregion - /// /// Gets a representation of the instance /// - public int Epoch => rawEpoch; + public int Epoch { get; private set; } /// /// Returns a representation of the instance /// - public DateTime DateTime => rawEpoch.ToDateTime(); - + public DateTime DateTime => Epoch.ToDateTime(); /// /// Returns a representation of the instance /// - public TimeSpan TimeSpan => rawEpoch.ToTimeSpan(); + public TimeSpan TimeSpan => Epoch.ToTimeSpan(); #if NET6_0_OR_GREATER /// /// Returns a representation of the instance /// - public DateOnly DateOnly => DateOnly.FromDateTime(rawEpoch.ToDateTime()); + public DateOnly DateOnly => DateOnly.FromDateTime(Epoch.ToDateTime()); /// /// Returns a representation of the instance /// - public TimeOnly TimeOnly => TimeOnly.FromDateTime(rawEpoch.ToDateTime()); + public TimeOnly TimeOnly => TimeOnly.FromDateTime(Epoch.ToDateTime()); #endif @@ -188,8 +174,8 @@ public static void ResetTimeProvider() /// public EpochTime Add(TimeSpan span) { - var newSpan = this.TimeSpan + span; - rawEpoch = newSpan.ToEpochTimestamp(); + var newSpan = TimeSpan + span; + Epoch = newSpan.ToEpochTimestamp(); return this; } @@ -208,14 +194,11 @@ public EpochTime Add(TimeSpan span) /// public static EpochTime operator +(EpochTime operand1, EpochTime operand2) { - var epochSum = operand1.Epoch + (long)operand2.Epoch; - - if (epochSum.IsValidEpochTimestamp() is false) - { - throw new EpochTimeValueException(epochSum); - } + long epochSum = operand1.Epoch + (long)operand2.Epoch; - return new EpochTime(Convert.ToInt32(epochSum)); + return epochSum.IsValidEpochTimestamp() is false + ? throw new EpochTimeValueException(epochSum) + : new EpochTime(Convert.ToInt32(epochSum)); } /// @@ -228,41 +211,24 @@ public EpochTime Add(TimeSpan span) /// If the result is not a valid public static EpochTime operator -(EpochTime operand1, EpochTime operand2) { - var epochSub = operand1.Epoch - (long)operand2.Epoch; + long epochSub = operand1.Epoch - (long)operand2.Epoch; - if (epochSub.IsValidEpochTimestamp() is false) - { - throw new EpochTimeValueException(epochSub); - } - - return new EpochTime(operand1.Epoch - operand2.Epoch); + return epochSub.IsValidEpochTimestamp() is false + ? throw new EpochTimeValueException(epochSub) + : new EpochTime(operand1.Epoch - operand2.Epoch); } #endregion #region Equals /// - public override bool Equals(object obj) - { - if (obj is EpochTime comparedEpoch) - { - return comparedEpoch.Epoch == Epoch; - } - - return false; - } + public override bool Equals(object obj) => obj is EpochTime comparedEpoch && comparedEpoch.Epoch == Epoch; /// - public override int GetHashCode() - { - return Epoch; - } + public override int GetHashCode() => Epoch; /// - public override string ToString() - { - return Epoch.ToString(); - } + public override string ToString() => Epoch.ToString(); #endregion } \ No newline at end of file diff --git a/Epoch.net/IntExtensions.cs b/Epoch.net/IntExtensions.cs index 6c9884f..7005f67 100644 --- a/Epoch.net/IntExtensions.cs +++ b/Epoch.net/IntExtensions.cs @@ -12,48 +12,33 @@ public static class IntExtensions /// /// The unix epoch /// A initialized to the given offset in seconds from 1970-01-01T00:00Z - public static DateTime ToDateTime(this int epoch) - { - return LongEpochTime.DefaultDateTime.AddSeconds(epoch); - } + public static DateTime ToDateTime(this int epoch) => LongEpochTime.DefaultDateTime.AddSeconds(epoch); /// /// Transforms the given into a structure /// /// The unix epoch /// A representing the offset of 1970-01-01T00:00Z - public static TimeSpan ToTimeSpan(this int epoch) - { - return TimeSpan.FromSeconds(epoch); - } + public static TimeSpan ToTimeSpan(this int epoch) => TimeSpan.FromSeconds(epoch); /// /// Transforms the given into a /// /// The unix epoch /// A initialized with the given unix epoch - public static EpochTime ToEpochTime(this int epoch) - { - return new EpochTime(epoch); - } + public static EpochTime ToEpochTime(this int epoch) => new(epoch); /// /// Transforms the given into a /// /// The unix epoch /// A initialized with the given unix epoch - public static LongEpochTime ToLongEpochTime(this int epoch) - { - return new LongEpochTime(epoch.ToLongEpochTimestamp()); - } + public static LongEpochTime ToLongEpochTime(this int epoch) => new(epoch.ToLongEpochTimestamp()); /// /// Transforms the given seconds offset into a millisecond offset /// /// The unix epoch /// The milliseconds from 1970-01-01T00:00Z - public static long ToLongEpochTimestamp(this int epoch) - { - return epoch * 1000L; - } + public static long ToLongEpochTimestamp(this int epoch) => epoch * 1000L; } \ No newline at end of file diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index 598774d..831fcdc 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -24,8 +24,8 @@ public sealed class LongEpochTime public const long MAX_VALUE = 922337203685477; public const long MIN_VALUE = -922337203685477; - public static LongEpochTime MIN => new LongEpochTime(MIN_VALUE); - public static LongEpochTime MAX => new LongEpochTime(MAX_VALUE); + public static LongEpochTime MIN => new(MIN_VALUE); + public static LongEpochTime MAX => new(MAX_VALUE); /// /// Initializes a new instance of @@ -160,7 +160,6 @@ public LongEpochTime Add(TimeSpan timeSpan) return new LongEpochTime(operator1.Epoch + operator2.Epoch); } - public static LongEpochTime operator -(LongEpochTime operator1, LongEpochTime operator2) { //todo: There is a open issue with long number underflow diff --git a/Epoch.net/LongEpochTimeValueException.cs b/Epoch.net/LongEpochTimeValueException.cs index 0d3e253..f31179e 100644 --- a/Epoch.net/LongEpochTimeValueException.cs +++ b/Epoch.net/LongEpochTimeValueException.cs @@ -8,7 +8,7 @@ namespace Epoch.net; public class LongEpochTimeValueException : Exception { private const string TimeSpanErrorMessage = "The provided TimeSpan {0} does not conform to the LongEpochTime range"; - + /// /// Creates a new instance of the with the given /// @@ -17,7 +17,7 @@ public class LongEpochTimeValueException : Exception /// It is assumed that the is not in a valid value range /// public LongEpochTimeValueException(TimeSpan value) - :base(string.Format(TimeSpanErrorMessage, value)) + : base(string.Format(TimeSpanErrorMessage, value)) { } } \ No newline at end of file diff --git a/Epoch.net/LongExtensions.cs b/Epoch.net/LongExtensions.cs index 62d8d51..2e98769 100644 --- a/Epoch.net/LongExtensions.cs +++ b/Epoch.net/LongExtensions.cs @@ -14,30 +14,21 @@ public static class LongExtensions /// /// True if the EpochTimestamp is in a valid range, False if not /// - public static bool IsValidEpochTimestamp(this long epoch) - { - return epoch >= EpochTime.MIN_VALUE && epoch <= EpochTime.MAX_VALUE; - } + public static bool IsValidEpochTimestamp(this long epoch) => epoch is >= EpochTime.MIN_VALUE and <= EpochTime.MAX_VALUE; /// /// Transforms the LongEpochTimestamp into a /// /// The LongEpochTimestamp /// A representation of the given LongEpochTimestamp - public static DateTime ToDateTime(this long value) - { - return LongEpochTime.DefaultDateTime.AddMilliseconds(value); - } + public static DateTime ToDateTime(this long value) => LongEpochTime.DefaultDateTime.AddMilliseconds(value); /// /// Transforms the LongEpochTimestamp into a /// /// The LongEpochTimestamp /// The representation of the LongEpochTimestamp - public static TimeSpan ToTimeSpan(this long value) - { - return TimeSpan.FromMilliseconds(value); - } + public static TimeSpan ToTimeSpan(this long value) => TimeSpan.FromMilliseconds(value); /// /// Transforms the LongEpochTimestamp into a EpochTimestamp @@ -51,14 +42,9 @@ public static TimeSpan ToTimeSpan(this long value) /// public static int ToEpochTimestamp(this long value) { - var seconds = value / 1000; + long seconds = value / 1000; - if (seconds.IsValidEpochTimestamp()) - { - return Convert.ToInt32(seconds); - } - - throw new EpochTimeValueException(value); + return seconds.IsValidEpochTimestamp() ? Convert.ToInt32(seconds) : throw new EpochTimeValueException(value); } /// @@ -66,8 +52,5 @@ public static int ToEpochTimestamp(this long value) /// /// The LongEpochTimestamp /// A initialized with the LongEpochTimestamp - public static LongEpochTime ToLongEpochTime(this long value) - { - return new LongEpochTime(value); - } + public static LongEpochTime ToLongEpochTime(this long value) => new(value); } \ No newline at end of file diff --git a/Epoch.net/TimeSpanExtensions.cs b/Epoch.net/TimeSpanExtensions.cs index b9e62b9..3290f86 100644 --- a/Epoch.net/TimeSpanExtensions.cs +++ b/Epoch.net/TimeSpanExtensions.cs @@ -12,10 +12,7 @@ public static class TimeSpanExtensions /// /// The given /// A new instance initialized with the given - public static EpochTime ToEpochTime(this TimeSpan timeSpan) - { - return new EpochTime(timeSpan); - } + public static EpochTime ToEpochTime(this TimeSpan timeSpan) => new(timeSpan); /// /// Transforms the given into a EpochTimestamp @@ -27,14 +24,9 @@ public static EpochTime ToEpochTime(this TimeSpan timeSpan) /// public static int ToEpochTimestamp(this TimeSpan timeSpan) { - var totalSeconds = timeSpan.TotalSeconds; - - if (!timeSpan.IsValidEpochTime()) - { - throw new EpochTimeValueException(timeSpan); - } + double totalSeconds = timeSpan.TotalSeconds; - return Convert.ToInt32(totalSeconds); + return !timeSpan.IsValidEpochTime() ? throw new EpochTimeValueException(timeSpan) : Convert.ToInt32(totalSeconds); } /// @@ -42,10 +34,7 @@ public static int ToEpochTimestamp(this TimeSpan timeSpan) /// /// The given /// A representation of the given - public static LongEpochTime ToLongEpochTime(this TimeSpan timeSpan) - { - return new LongEpochTime(timeSpan); - } + public static LongEpochTime ToLongEpochTime(this TimeSpan timeSpan) => new(timeSpan); /// /// Transforms the given into a LongEpochTimestamp @@ -57,14 +46,9 @@ public static LongEpochTime ToLongEpochTime(this TimeSpan timeSpan) /// public static long ToLongEpochTimestamp(this TimeSpan timeSpan) { - var totalMilliseconds = timeSpan.TotalMilliseconds; - - if (!timeSpan.IsValidLongEpochTime()) - { - throw new LongEpochTimeValueException(timeSpan); - } + double totalMilliseconds = timeSpan.TotalMilliseconds; - return Convert.ToInt64(totalMilliseconds); + return !timeSpan.IsValidLongEpochTime() ? throw new LongEpochTimeValueException(timeSpan) : Convert.ToInt64(totalMilliseconds); } /// @@ -76,9 +60,9 @@ public static long ToLongEpochTimestamp(this TimeSpan timeSpan) /// public static bool IsValidEpochTime(this TimeSpan timeSpan) { - var totalSeconds = timeSpan.TotalSeconds; + double totalSeconds = timeSpan.TotalSeconds; - return totalSeconds >= EpochTime.MIN_VALUE && totalSeconds <= EpochTime.MAX_VALUE; + return totalSeconds is >= EpochTime.MIN_VALUE and <= EpochTime.MAX_VALUE; } /// @@ -90,8 +74,8 @@ public static bool IsValidEpochTime(this TimeSpan timeSpan) /// public static bool IsValidLongEpochTime(this TimeSpan timeSpan) { - var totalMilliseconds = timeSpan.TotalMilliseconds; + double totalMilliseconds = timeSpan.TotalMilliseconds; - return totalMilliseconds >= LongEpochTime.MIN_VALUE && totalMilliseconds <= LongEpochTime.MAX_VALUE; + return totalMilliseconds is >= LongEpochTime.MIN_VALUE and <= LongEpochTime.MAX_VALUE; } } \ No newline at end of file From 9b2a588a455c4c22a5b2bda806de630a7f2cb45e Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 11 Nov 2023 21:12:25 +0100 Subject: [PATCH 12/14] Removed warnings --- Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs | 2 ++ Epoch.net/DateOnlyExtensions.cs | 3 ++ Epoch.net/LongEpochTime.cs | 32 +++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs b/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs index 171c900..41f4a30 100644 --- a/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs +++ b/Epoch.net.Test/LongEpochTime_Ctor_Fixture.cs @@ -15,6 +15,8 @@ public class LongEpochTime_Ctor_Fixture public void Long() { Assert.AreEqual(0L, new LongEpochTime(0L).Epoch); + + Assert.AreEqual(LongEpochTime.Default, new LongEpochTime(LongEpochTime.DefaultDateTime)); Assert.AreEqual(ValidLongEpochTimestamp, new LongEpochTime(ValidLongEpochTimestamp).Epoch); } diff --git a/Epoch.net/DateOnlyExtensions.cs b/Epoch.net/DateOnlyExtensions.cs index 50fe03e..a441121 100644 --- a/Epoch.net/DateOnlyExtensions.cs +++ b/Epoch.net/DateOnlyExtensions.cs @@ -2,6 +2,9 @@ namespace Epoch.net; #if NET6_0_OR_GREATER +/// +/// Implements Epoch extentions on the type +/// public static class DateOnlyExtensions { /// diff --git a/Epoch.net/LongEpochTime.cs b/Epoch.net/LongEpochTime.cs index 831fcdc..f521003 100644 --- a/Epoch.net/LongEpochTime.cs +++ b/Epoch.net/LongEpochTime.cs @@ -19,12 +19,30 @@ public sealed class LongEpochTime /// public static LongEpochTime Default => new(0); + /// + /// The default date time value of an + /// + /// /// + /// Thursday, January 1, 1970 12:00:00 AM GMT + /// public static DateTime DefaultDateTime => new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + /// + /// The minimal possible value of a + /// public const long MAX_VALUE = 922337203685477; + /// + /// The maximal possible value of a + /// public const long MIN_VALUE = -922337203685477; + /// + /// The minimal value of a + /// public static LongEpochTime MIN => new(MIN_VALUE); + /// + /// The maximal value of a + /// public static LongEpochTime MAX => new(MAX_VALUE); /// @@ -93,7 +111,7 @@ public LongEpochTime(EpochTime epochTime) private long rawEpoch { get; set; } /// - /// Injects a new global thread safe instance to be used globally + /// Injects a new global thread safe instance to be used globally /// /// The new time provider instance public static void SetTimeProvider(IDateTimeProvider timeProvider) @@ -153,6 +171,12 @@ public LongEpochTime Add(TimeSpan timeSpan) public LongEpochTime Add(TimeOnly time) => this; #endif + /// + /// Implements the + operator between two instances + /// + /// The augend + /// The addend + /// The sum of the two public static LongEpochTime operator +(LongEpochTime operator1, LongEpochTime operator2) { // todo: There is a open issue with long number overflow @@ -160,6 +184,12 @@ public LongEpochTime Add(TimeSpan timeSpan) return new LongEpochTime(operator1.Epoch + operator2.Epoch); } + /// + /// Implements the - operator between two instances + /// + /// The minuend + /// The subtrahend + /// The Difference between the two instances public static LongEpochTime operator -(LongEpochTime operator1, LongEpochTime operator2) { //todo: There is a open issue with long number underflow From 6b4d399616b0f64912fa6390befee02c16f3f20d Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 11 Nov 2023 21:54:58 +0100 Subject: [PATCH 13/14] created seperate build for master PR --- .github/workflows/dotnet.yml | 2 -- .github/workflows/master_pr.yml | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/master_pr.yml diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 1464e17..eb2c6b8 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -6,8 +6,6 @@ name: BuildAndTest on: push: branches: [ "*" ] - pull_request: - branches: [ "master" ] jobs: build: diff --git a/.github/workflows/master_pr.yml b/.github/workflows/master_pr.yml new file mode 100644 index 0000000..4329f2d --- /dev/null +++ b/.github/workflows/master_pr.yml @@ -0,0 +1,28 @@ +# This workflow will build a .NET project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net + +name: master_pr + +on: + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 7.0.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore -warnaserror + - name: Test + run: dotnet test --verbosity normal From 4b69356e45414dcdfdc2253874e91c43e62116f3 Mon Sep 17 00:00:00 2001 From: Dejan FAJFAR Date: Sat, 11 Nov 2023 22:09:34 +0100 Subject: [PATCH 14/14] Update README.md --- README.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4f5629e..86050a4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ -[![Build status](https://ci.appveyor.com/api/projects/status/3k10iipudlw1v9va?svg=true)](https://ci.appveyor.com/project/dejanfajfar/epoch-net) -[![Build status](https://ci.appveyor.com/api/projects/status/3k10iipudlw1v9va/branch/master?svg=true)](https://ci.appveyor.com/project/dejanfajfar/epoch-net/branch/master) -[![](https://img.shields.io/nuget/v/epoch.net.svg)](https://www.nuget.org/packages/Epoch.net/) -![](https://img.shields.io/nuget/dt/epoch.net.svg) -[![Gitter](https://img.shields.io/gitter/room/dejanfajfar/epoch.net.svg)](https://gitter.im/dejanfajfar/epoch.net) +![Nuget](https://img.shields.io/nuget/dt/epoch.net?style=flat-square&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FEpoch.net) +![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/epoch.net?style=flat-square&link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FEpoch.net) ![](https://raw.githubusercontent.com/dejanfajfar/epoch.net/master/images/logo.png) @@ -194,10 +191,3 @@ var timeSpan = (timestamp1 - timestamp2).ToTimeSpan(); ### And much more... More scenarios can be found in the wiki... - -## Next steps - -Check out the chat -[![Gitter](https://img.shields.io/gitter/room/dejanfajfar/epoch.net.svg)](https://gitter.im/dejanfajfar/epoch.net) - -Or the wiki (if I have created one yet) :) \ No newline at end of file