//******************************************************************************************************// Ticks.cs - Gbtc//// Copyright © 2010, Grid Protection Alliance. All Rights Reserved.//// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See// the NOTICE file distributed with this work for additional information regarding copyright ownership.// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may// not use this file except in compliance with the License. You may obtain a copy of the License at://// http://www.opensource.org/licenses/eclipse-1.0.php//// Unless agreed to in writing, the subject software distributed under the License is distributed on an// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the// License for the specific language governing permissions and limitations.//// Code Modification History:// ----------------------------------------------------------------------------------------------------// 11/12/2004 - J. Ritchie Carroll// Initial version of source generated.// 08/4/2009 - Josh L. Patterson// Edited Code Comments.// 09/14/2009 - Stephen C. Wills// Added new header and license agreement.// 10/8/2012 - Danyelle Gilliam// Modified Header////****************************************************************************************************** #region [ Contributor License Agreements ] /**************************************************************************\ Copyright © 2009 - J. Ritchie Carroll All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \**************************************************************************/ #endregion using GSF.Units;using System;using System.ComponentModel;using System.Globalization;using System.Runtime.CompilerServices;using System.Text; namespace GSF{ #region [ Enumerations ] /// <summary> /// Time intervals enumeration used by <see cref="Ticks.BaselinedTimestamp"/> method. /// </summary> public enum BaselineTimeInterval { /// <summary>Baseline timestamp to the second (i.e., starting at zero milliseconds).</summary> Second, /// <summary>Baseline timestamp to the minute (i.e., starting at zero seconds and milliseconds).</summary> Minute, /// <summary>Baseline timestamp to the hour (i.e., starting at zero minutes, seconds and milliseconds).</summary> Hour, /// <summary>Baseline timestamp to the day (i.e., starting at zero hours, minutes, seconds and milliseconds).</summary> Day, /// <summary>Baseline timestamp to the month (i.e., starting at day one, zero hours, minutes, seconds and milliseconds).</summary> Month, /// <summary>Baseline timestamp to the year (i.e., starting at month one, day one, zero hours, minutes, seconds and milliseconds).</summary> Year } #endregion /// <summary> /// Represents an instant in time, or time period, as a 64-bit signed integer with a value that is expressed as the number /// of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. /// </summary> /// <remarks> /// <para> /// <see cref="Ticks"/> can represent an "instant in time" and therefore can be used exactly like a <see cref="DateTime"/>. /// The difference between <see cref="Ticks"/> and <see cref="DateTime"/> is that <see cref="Ticks"/> is essentially a long /// integer (i.e., an <see cref="Int64"/>) which represents the number of ticks that have elapsed since 12:00:00 midnight, /// January 1, 0001 with each tick having a resolution of 100-nanoseconds. You would use <see cref="Ticks"/> in places where /// you needed to directly represent time in high-resolution, i.e., time with subsecond accuracy, using an object that will /// act like a long integer but handle time conversions. <see cref="Ticks"/> can also represent a "time period" (e.g., the /// number of ticks elapsed since a process started) and thus can also be used like a <see cref="TimeSpan"/>; when used in /// this manner the <see cref="Ticks.ToElapsedTimeString()"/> method can be used to convert the <see cref="Ticks"/> value /// into a handy textual representation of elapsed years, days, hours, minutes and seconds. /// </para> /// <para> /// This class behaves just like an <see cref="Int64"/> representing a time in ticks; it is implictly castable to and from /// an <see cref="Int64"/> and therefore can be generally used "as" an Int64 directly. It is also implicitly castable to and /// from a <see cref="DateTime"/>, a <see cref="TimeSpan"/>, an <see cref="NtpTimeTag"/> and a <see cref="UnixTimeTag"/>. /// </para> /// </remarks> [Serializable()] public struct Ticks : IComparable, IFormattable, IConvertible, IComparable<Ticks>, IComparable<Int64>, IComparable<DateTime>, IComparable<TimeSpan>, IEquatable<Ticks>, IEquatable<Int64>, IEquatable<DateTime>, IEquatable<TimeSpan> { #region [ Members ] // Nested Types private struct TimeName { // Note that this is a structure so that elements may be used as an // index into a string array without having to cast as (int) public const int Year = 0; public const int Years = 1; public const int Day = 2; public const int Days = 3; public const int Hour = 4; public const int Hours = 5; public const int Minute = 6; public const int Minutes = 7; public const int Second = 8; public const int Seconds = 9; public const int LessThan60Seconds = 10; public const int NoSeconds = 11; } // Constants // Standard time names used by ToString method private static string[] s_timeNames = new string[] { " Year", " Years", " Day", " Days", " Hour", " Hours", " Minute", " Minutes", " Second", " Seconds", "Less Than 60 Seconds", "0 Seconds" }; // Standard time names, without seconds, used by ToString method private static string[] s_timeNamesNoSeconds = new string[] { " Year", " Years", " Day", " Days", " Hour", " Hours", " Minute", " Minutes", " Second", " Seconds", "Less Than 1 Minute", "0 Minutes" }; /// <summary>Number of 100-nanosecond ticks in one second.</summary> public const long PerSecond = 10000000L; /// <summary>Number of 100-nanosecond ticks in one millisecond.</summary> public const long PerMillisecond = (long)(Ticks.PerSecond * SI.Milli); /// <summary>Number of 100-nanosecond ticks in one microsecond.</summary> public const long PerMicrosecond = (long)(Ticks.PerSecond * SI.Micro); /// <summary>Number of 100-nanosecond ticks in one minute.</summary> public const long PerMinute = 60L * Ticks.PerSecond; /// <summary>Number of 100-nanosecond ticks in one hour.</summary> public const long PerHour = 60L * Ticks.PerMinute; /// <summary>Number of 100-nanosecond ticks in one day.</summary> public const long PerDay = 24L * Ticks.PerHour; // Fields private long m_value; // Time value stored in ticks #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="Ticks"/>. /// </summary> /// <param name="value">New time value in ticks.</param> public Ticks(long value) { m_value = value; } /// <summary> /// Creates a new <see cref="Ticks"/>. /// </summary> /// <param name="value">New time value as a <see cref="DateTime"/>.</param> public Ticks(DateTime value) { m_value = value.Ticks; } /// <summary> /// Creates a new <see cref="Ticks"/>. /// </summary> /// <param name="value">New time value as a <see cref="TimeSpan"/>.</param> public Ticks(TimeSpan value) { m_value = value.Ticks; } #endregion #region [ Methods ] /// <summary> /// Gets the <see cref="Ticks"/> value in equivalent number of seconds. /// </summary> /// <returns>Value of <see cref="Ticks"/> in seconds.</returns> /// <remarks> /// If <see cref="Ticks"/> value represents an instant in time, returned value will represent the number of seconds /// that have elapsed since 12:00:00 midnight, January 1, 0001. /// </remarks> public double ToSeconds() { return m_value / (double)Ticks.PerSecond; } /// <summary> /// Gets the <see cref="Ticks"/> value in equivalent number of milliseconds. /// </summary> /// <returns>Value of <see cref="Ticks"/> in milliseconds.</returns> /// <remarks> /// If <see cref="Ticks"/> value represents an instant in time, returned value will represent the number of milliseconds /// that have elapsed since 12:00:00 midnight, January 1, 0001. /// </remarks> public double ToMilliseconds() { return m_value / (double)Ticks.PerMillisecond; } /// <summary> /// Gets the <see cref="Ticks"/> value in equivalent number of microseconds. /// </summary> /// <returns>Value of <see cref="Ticks"/> in microseconds.</returns> /// <remarks> /// If <see cref="Ticks"/> value represents an instant in time, returned value will represent the number of microseconds /// that have elapsed since 12:00:00 midnight, January 1, 0001. /// </remarks> public double ToMicroseconds() { return m_value / (double)Ticks.PerMicrosecond; } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in UTC time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in seconds, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in seconds, before assuming time is too advanced to be valid.</param> /// <returns>True, if UTC time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of system clock time in UTC. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be set /// to sub-second intervals. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be less than one. /// </exception> public bool UtcTimeIsValid(double lagTime, double leadTime) { return TimeIsValid(DateTime.UtcNow.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in UTC time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in ticks, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in ticks, before assuming time is too advanced to be valid.</param> /// <returns>True, if UTC time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of system clock time in UTC. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </exception> public bool UtcTimeIsValid(Ticks lagTime, Ticks leadTime) { return TimeIsValid(DateTime.UtcNow.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in local time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in seconds, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in seconds, before assuming time is too advanced to be valid.</param> /// <returns>True, if local time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of local system clock time. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be set /// to sub-second intervals. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be less than one. /// </exception> public bool LocalTimeIsValid(double lagTime, double leadTime) { return TimeIsValid(DateTime.Now.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in local time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in ticks, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in ticks, before assuming time is too advanced to be valid.</param> /// <returns>True, if local time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of local system clock time. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </exception> public bool LocalTimeIsValid(Ticks lagTime, Ticks leadTime) { return TimeIsValid(DateTime.Now.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value, is valid by comparing it to the specified /// current time. /// </summary> /// <param name="currentTime">Specified current time (e.g., could be DateTime.Now.Ticks).</param> /// <param name="lagTime">The allowed lag time, in seconds, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in seconds, before assuming time is too advanced to be valid.</param> /// <returns>True, if time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of <paramref name="currentTime"/>. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be set /// to sub-second intervals. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be less than one. /// </exception> public bool TimeIsValid(Ticks currentTime, double lagTime, double leadTime) { if (lagTime <= 0) throw new ArgumentOutOfRangeException("lagTime", "lagTime must be greater than zero, but it can be less than one"); if (leadTime <= 0) throw new ArgumentOutOfRangeException("leadTime", "leadTime must be greater than zero, but it can be less than one"); double distance = (currentTime.m_value - m_value) / (double)Ticks.PerSecond; return (distance >= -leadTime && distance <= lagTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value, is valid by comparing it to the specified /// current time. /// </summary> /// <param name="currentTime">Specified current time (e.g., could be DateTime.Now.Ticks).</param> /// <param name="lagTime">The allowed lag time, in ticks, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in ticks, before assuming time is too advanced to be valid.</param> /// <returns>True, if time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of <paramref name="currentTime"/>. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </exception> public bool TimeIsValid(Ticks currentTime, Ticks lagTime, Ticks leadTime) { if (lagTime.m_value <= 0) throw new ArgumentOutOfRangeException("lagTime", "lagTime must be greater than zero"); if (leadTime.m_value <= 0) throw new ArgumentOutOfRangeException("leadTime", "leadTime must be greater than zero"); long distance = (currentTime.m_value - m_value); return (distance >= -leadTime.m_value && distance <= lagTime.m_value); } /// <summary> /// Gets the distance, in 100-nanoseconds intervals, beyond the top of the second in the timestamp /// represented by the <see cref="Ticks"/>. /// </summary> /// <returns> /// Number of 100-nanoseconds intervals <see cref="Ticks"/> value is from the top of the second. /// </returns> public Ticks DistanceBeyondSecond() { return m_value - (m_value - m_value % Ticks.PerSecond); } /// <summary> /// Creates a new <see cref="Ticks"/> value that represents a baselined timestamp, in 100-nanoseconds /// intervals, that begins at the beginning of the specified time interval. /// </summary> /// <param name="interval"> /// <see cref="BaselineTimeInterval"/> to which <see cref="Ticks"/> timestamp should be baselined. /// </param> /// <returns> /// A new <see cref="Ticks"/> value that represents a baselined timestamp, in 100-nanoseconds intervals, /// that begins at the specified <see cref="BaselineTimeInterval"/>. /// </returns> /// <remarks> /// Baselining to the <see cref="BaselineTimeInterval.Second"/> would return the <see cref="Ticks"/> /// value starting at zero milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Minute"/> would return the <see cref="Ticks"/> /// value starting at zero seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Hour"/> would return the <see cref="Ticks"/> /// value starting at zero minutes, seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Day"/> would return the <see cref="Ticks"/> /// value starting at zero hours, minutes, seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Month"/> would return the <see cref="Ticks"/> /// value starting at day one, zero hours, minutes, seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Year"/> would return the <see cref="Ticks"/> /// value starting at month one, day one, zero hours, minutes, seconds and milliseconds. /// </remarks> public Ticks BaselinedTimestamp(BaselineTimeInterval interval) { switch (interval) { case BaselineTimeInterval.Second: return m_value - m_value % Ticks.PerSecond; case BaselineTimeInterval.Minute: return m_value - m_value % Ticks.PerMinute; case BaselineTimeInterval.Hour: return m_value - m_value % Ticks.PerHour; case BaselineTimeInterval.Day: return m_value - m_value % Ticks.PerDay; case BaselineTimeInterval.Month: DateTime toMonth = new DateTime(m_value); return new DateTime(toMonth.Year, toMonth.Month, 1, 0, 0, 0, 0).Ticks; case BaselineTimeInterval.Year: return new DateTime((new DateTime(m_value)).Year, 1, 1, 0, 0, 0, 0).Ticks; default: return this; } } /// <summary> /// Converts the value of the <see cref="Ticks"/> value to its equivalent <see cref="DateTime"/> string representation. /// </summary> /// <returns>A <see cref="DateTime"/> string representation of the <see cref="Ticks"/> value.</returns> public override string ToString() { return ((DateTime)this).ToString(); } /// <summary> /// Converts the <see cref="Ticks"/> value to its equivalent string representation, using /// the specified <see cref="DateTime"/> format. /// </summary> /// <param name="format">A format string.</param> /// <returns> /// The string representation of the value of this instance as specified by format. /// </returns> public string ToString(string format) { return ((DateTime)this).ToString(format); } /// <summary> /// Converts the <see cref="Ticks"/> value to its equivalent string representation, using /// the specified culture-specific <see cref="DateTime"/> format information. /// </summary> /// <param name="provider"> /// A <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information. /// </param> /// <returns> /// The string representation of the value of this instance as specified by provider. /// </returns> public string ToString(IFormatProvider provider) { return ((DateTime)this).ToString(provider); } /// <summary> /// Converts the <see cref="Ticks"/> value to its equivalent string representation, using /// specified format and culture-specific <see cref="DateTime"/> format information. /// </summary> /// <param name="format">A format specification.</param> /// <param name="provider"> /// A <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information. /// </param> /// <returns> /// The string representation of the value of this instance as specified by format and provider. /// </returns> public string ToString(string format, IFormatProvider provider) { return ((DateTime)this).ToString(format, provider); } /// <summary>Lines 1–500 of 1513. Load more
//****************************************************************************************************** // Ticks.cs - Gbtc // // Copyright © 2010, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/eclipse-1.0.php // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 11/12/2004 - J. Ritchie Carroll // Initial version of source generated. // 08/4/2009 - Josh L. Patterson // Edited Code Comments. // 09/14/2009 - Stephen C. Wills // Added new header and license agreement. // 10/8/2012 - Danyelle Gilliam // Modified Header // //****************************************************************************************************** #region [ Contributor License Agreements ] /**************************************************************************\ Copyright © 2009 - J. Ritchie Carroll All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \**************************************************************************/ #endregion using GSF.Units; using System; using System.ComponentModel; using System.Globalization; using System.Runtime.CompilerServices; using System.Text; namespace GSF { #region [ Enumerations ] /// <summary> /// Time intervals enumeration used by <see cref="Ticks.BaselinedTimestamp"/> method. /// </summary> public enum BaselineTimeInterval { /// <summary>Baseline timestamp to the second (i.e., starting at zero milliseconds).</summary> Second, /// <summary>Baseline timestamp to the minute (i.e., starting at zero seconds and milliseconds).</summary> Minute, /// <summary>Baseline timestamp to the hour (i.e., starting at zero minutes, seconds and milliseconds).</summary> Hour, /// <summary>Baseline timestamp to the day (i.e., starting at zero hours, minutes, seconds and milliseconds).</summary> Day, /// <summary>Baseline timestamp to the month (i.e., starting at day one, zero hours, minutes, seconds and milliseconds).</summary> Month, /// <summary>Baseline timestamp to the year (i.e., starting at month one, day one, zero hours, minutes, seconds and milliseconds).</summary> Year } #endregion /// <summary> /// Represents an instant in time, or time period, as a 64-bit signed integer with a value that is expressed as the number /// of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. /// </summary> /// <remarks> /// <para> /// <see cref="Ticks"/> can represent an "instant in time" and therefore can be used exactly like a <see cref="DateTime"/>. /// The difference between <see cref="Ticks"/> and <see cref="DateTime"/> is that <see cref="Ticks"/> is essentially a long /// integer (i.e., an <see cref="Int64"/>) which represents the number of ticks that have elapsed since 12:00:00 midnight, /// January 1, 0001 with each tick having a resolution of 100-nanoseconds. You would use <see cref="Ticks"/> in places where /// you needed to directly represent time in high-resolution, i.e., time with subsecond accuracy, using an object that will /// act like a long integer but handle time conversions. <see cref="Ticks"/> can also represent a "time period" (e.g., the /// number of ticks elapsed since a process started) and thus can also be used like a <see cref="TimeSpan"/>; when used in /// this manner the <see cref="Ticks.ToElapsedTimeString()"/> method can be used to convert the <see cref="Ticks"/> value /// into a handy textual representation of elapsed years, days, hours, minutes and seconds. /// </para> /// <para> /// This class behaves just like an <see cref="Int64"/> representing a time in ticks; it is implictly castable to and from /// an <see cref="Int64"/> and therefore can be generally used "as" an Int64 directly. It is also implicitly castable to and /// from a <see cref="DateTime"/>, a <see cref="TimeSpan"/>, an <see cref="NtpTimeTag"/> and a <see cref="UnixTimeTag"/>. /// </para> /// </remarks> [Serializable()] public struct Ticks : IComparable, IFormattable, IConvertible, IComparable<Ticks>, IComparable<Int64>, IComparable<DateTime>, IComparable<TimeSpan>, IEquatable<Ticks>, IEquatable<Int64>, IEquatable<DateTime>, IEquatable<TimeSpan> { #region [ Members ] // Nested Types private struct TimeName { // Note that this is a structure so that elements may be used as an // index into a string array without having to cast as (int) public const int Year = 0; public const int Years = 1; public const int Day = 2; public const int Days = 3; public const int Hour = 4; public const int Hours = 5; public const int Minute = 6; public const int Minutes = 7; public const int Second = 8; public const int Seconds = 9; public const int LessThan60Seconds = 10; public const int NoSeconds = 11; } // Constants // Standard time names used by ToString method private static string[] s_timeNames = new string[] { " Year", " Years", " Day", " Days", " Hour", " Hours", " Minute", " Minutes", " Second", " Seconds", "Less Than 60 Seconds", "0 Seconds" }; // Standard time names, without seconds, used by ToString method private static string[] s_timeNamesNoSeconds = new string[] { " Year", " Years", " Day", " Days", " Hour", " Hours", " Minute", " Minutes", " Second", " Seconds", "Less Than 1 Minute", "0 Minutes" }; /// <summary>Number of 100-nanosecond ticks in one second.</summary> public const long PerSecond = 10000000L; /// <summary>Number of 100-nanosecond ticks in one millisecond.</summary> public const long PerMillisecond = (long)(Ticks.PerSecond * SI.Milli); /// <summary>Number of 100-nanosecond ticks in one microsecond.</summary> public const long PerMicrosecond = (long)(Ticks.PerSecond * SI.Micro); /// <summary>Number of 100-nanosecond ticks in one minute.</summary> public const long PerMinute = 60L * Ticks.PerSecond; /// <summary>Number of 100-nanosecond ticks in one hour.</summary> public const long PerHour = 60L * Ticks.PerMinute; /// <summary>Number of 100-nanosecond ticks in one day.</summary> public const long PerDay = 24L * Ticks.PerHour; // Fields private long m_value; // Time value stored in ticks #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="Ticks"/>. /// </summary> /// <param name="value">New time value in ticks.</param> public Ticks(long value) { m_value = value; } /// <summary> /// Creates a new <see cref="Ticks"/>. /// </summary> /// <param name="value">New time value as a <see cref="DateTime"/>.</param> public Ticks(DateTime value) { m_value = value.Ticks; } /// <summary> /// Creates a new <see cref="Ticks"/>. /// </summary> /// <param name="value">New time value as a <see cref="TimeSpan"/>.</param> public Ticks(TimeSpan value) { m_value = value.Ticks; } #endregion #region [ Methods ] /// <summary> /// Gets the <see cref="Ticks"/> value in equivalent number of seconds. /// </summary> /// <returns>Value of <see cref="Ticks"/> in seconds.</returns> /// <remarks> /// If <see cref="Ticks"/> value represents an instant in time, returned value will represent the number of seconds /// that have elapsed since 12:00:00 midnight, January 1, 0001. /// </remarks> public double ToSeconds() { return m_value / (double)Ticks.PerSecond; } /// <summary> /// Gets the <see cref="Ticks"/> value in equivalent number of milliseconds. /// </summary> /// <returns>Value of <see cref="Ticks"/> in milliseconds.</returns> /// <remarks> /// If <see cref="Ticks"/> value represents an instant in time, returned value will represent the number of milliseconds /// that have elapsed since 12:00:00 midnight, January 1, 0001. /// </remarks> public double ToMilliseconds() { return m_value / (double)Ticks.PerMillisecond; } /// <summary> /// Gets the <see cref="Ticks"/> value in equivalent number of microseconds. /// </summary> /// <returns>Value of <see cref="Ticks"/> in microseconds.</returns> /// <remarks> /// If <see cref="Ticks"/> value represents an instant in time, returned value will represent the number of microseconds /// that have elapsed since 12:00:00 midnight, January 1, 0001. /// </remarks> public double ToMicroseconds() { return m_value / (double)Ticks.PerMicrosecond; } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in UTC time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in seconds, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in seconds, before assuming time is too advanced to be valid.</param> /// <returns>True, if UTC time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of system clock time in UTC. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be set /// to sub-second intervals. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be less than one. /// </exception> public bool UtcTimeIsValid(double lagTime, double leadTime) { return TimeIsValid(DateTime.UtcNow.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in UTC time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in ticks, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in ticks, before assuming time is too advanced to be valid.</param> /// <returns>True, if UTC time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of system clock time in UTC. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </exception> public bool UtcTimeIsValid(Ticks lagTime, Ticks leadTime) { return TimeIsValid(DateTime.UtcNow.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in local time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in seconds, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in seconds, before assuming time is too advanced to be valid.</param> /// <returns>True, if local time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of local system clock time. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be set /// to sub-second intervals. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be less than one. /// </exception> public bool LocalTimeIsValid(double lagTime, double leadTime) { return TimeIsValid(DateTime.Now.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value in local time, is valid by comparing it to /// the system clock. /// </summary> /// <param name="lagTime">The allowed lag time, in ticks, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in ticks, before assuming time is too advanced to be valid.</param> /// <returns>True, if local time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of local system clock time. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </exception> public bool LocalTimeIsValid(Ticks lagTime, Ticks leadTime) { return TimeIsValid(DateTime.Now.Ticks, lagTime, leadTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value, is valid by comparing it to the specified /// current time. /// </summary> /// <param name="currentTime">Specified current time (e.g., could be DateTime.Now.Ticks).</param> /// <param name="lagTime">The allowed lag time, in seconds, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in seconds, before assuming time is too advanced to be valid.</param> /// <returns>True, if time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of <paramref name="currentTime"/>. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be set /// to sub-second intervals. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero, but can be less than one. /// </exception> public bool TimeIsValid(Ticks currentTime, double lagTime, double leadTime) { if (lagTime <= 0) throw new ArgumentOutOfRangeException("lagTime", "lagTime must be greater than zero, but it can be less than one"); if (leadTime <= 0) throw new ArgumentOutOfRangeException("leadTime", "leadTime must be greater than zero, but it can be less than one"); double distance = (currentTime.m_value - m_value) / (double)Ticks.PerSecond; return (distance >= -leadTime && distance <= lagTime); } /// <summary> /// Determines if time, represented by <see cref="Ticks"/> value, is valid by comparing it to the specified /// current time. /// </summary> /// <param name="currentTime">Specified current time (e.g., could be DateTime.Now.Ticks).</param> /// <param name="lagTime">The allowed lag time, in ticks, before assuming time is too old to be valid.</param> /// <param name="leadTime">The allowed lead time, in ticks, before assuming time is too advanced to be valid.</param> /// <returns>True, if time represented by <see cref="Ticks"/> value, is within the specified range.</returns> /// <remarks> /// Time, represented by <see cref="Ticks"/> value, is considered valid if it exists within the specified /// <paramref name="lagTime"/> and <paramref name="leadTime"/> range of <paramref name="currentTime"/>. Note /// that <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="lagTime"/> and <paramref name="leadTime"/> must be greater than zero. /// </exception> public bool TimeIsValid(Ticks currentTime, Ticks lagTime, Ticks leadTime) { if (lagTime.m_value <= 0) throw new ArgumentOutOfRangeException("lagTime", "lagTime must be greater than zero"); if (leadTime.m_value <= 0) throw new ArgumentOutOfRangeException("leadTime", "leadTime must be greater than zero"); long distance = (currentTime.m_value - m_value); return (distance >= -leadTime.m_value && distance <= lagTime.m_value); } /// <summary> /// Gets the distance, in 100-nanoseconds intervals, beyond the top of the second in the timestamp /// represented by the <see cref="Ticks"/>. /// </summary> /// <returns> /// Number of 100-nanoseconds intervals <see cref="Ticks"/> value is from the top of the second. /// </returns> public Ticks DistanceBeyondSecond() { return m_value - (m_value - m_value % Ticks.PerSecond); } /// <summary> /// Creates a new <see cref="Ticks"/> value that represents a baselined timestamp, in 100-nanoseconds /// intervals, that begins at the beginning of the specified time interval. /// </summary> /// <param name="interval"> /// <see cref="BaselineTimeInterval"/> to which <see cref="Ticks"/> timestamp should be baselined. /// </param> /// <returns> /// A new <see cref="Ticks"/> value that represents a baselined timestamp, in 100-nanoseconds intervals, /// that begins at the specified <see cref="BaselineTimeInterval"/>. /// </returns> /// <remarks> /// Baselining to the <see cref="BaselineTimeInterval.Second"/> would return the <see cref="Ticks"/> /// value starting at zero milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Minute"/> would return the <see cref="Ticks"/> /// value starting at zero seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Hour"/> would return the <see cref="Ticks"/> /// value starting at zero minutes, seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Day"/> would return the <see cref="Ticks"/> /// value starting at zero hours, minutes, seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Month"/> would return the <see cref="Ticks"/> /// value starting at day one, zero hours, minutes, seconds and milliseconds.<br/> /// Baselining to the <see cref="BaselineTimeInterval.Year"/> would return the <see cref="Ticks"/> /// value starting at month one, day one, zero hours, minutes, seconds and milliseconds. /// </remarks> public Ticks BaselinedTimestamp(BaselineTimeInterval interval) { switch (interval) { case BaselineTimeInterval.Second: return m_value - m_value % Ticks.PerSecond; case BaselineTimeInterval.Minute: return m_value - m_value % Ticks.PerMinute; case BaselineTimeInterval.Hour: return m_value - m_value % Ticks.PerHour; case BaselineTimeInterval.Day: return m_value - m_value % Ticks.PerDay; case BaselineTimeInterval.Month: DateTime toMonth = new DateTime(m_value); return new DateTime(toMonth.Year, toMonth.Month, 1, 0, 0, 0, 0).Ticks; case BaselineTimeInterval.Year: return new DateTime((new DateTime(m_value)).Year, 1, 1, 0, 0, 0, 0).Ticks; default: return this; } } /// <summary> /// Converts the value of the <see cref="Ticks"/> value to its equivalent <see cref="DateTime"/> string representation. /// </summary> /// <returns>A <see cref="DateTime"/> string representation of the <see cref="Ticks"/> value.</returns> public override string ToString() { return ((DateTime)this).ToString(); } /// <summary> /// Converts the <see cref="Ticks"/> value to its equivalent string representation, using /// the specified <see cref="DateTime"/> format. /// </summary> /// <param name="format">A format string.</param> /// <returns> /// The string representation of the value of this instance as specified by format. /// </returns> public string ToString(string format) { return ((DateTime)this).ToString(format); } /// <summary> /// Converts the <see cref="Ticks"/> value to its equivalent string representation, using /// the specified culture-specific <see cref="DateTime"/> format information. /// </summary> /// <param name="provider"> /// A <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information. /// </param> /// <returns> /// The string representation of the value of this instance as specified by provider. /// </returns> public string ToString(IFormatProvider provider) { return ((DateTime)this).ToString(provider); } /// <summary> /// Converts the <see cref="Ticks"/> value to its equivalent string representation, using /// specified format and culture-specific <see cref="DateTime"/> format information. /// </summary> /// <param name="format">A format specification.</param> /// <param name="provider"> /// A <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information. /// </param> /// <returns> /// The string representation of the value of this instance as specified by format and provider. /// </returns> public string ToString(string format, IFormatProvider provider) { return ((DateTime)this).ToString(format, provider); } /// <summary>