HighPrecisionTimeStamps 1.0.0.6

.NET Standard 2.0
There is a newer prerelease version of this package available.
See the version list below for details.
NuGet\Install-Package HighPrecisionTimeStamps -Version 1.0.0.6
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
dotnet add package HighPrecisionTimeStamps --version 1.0.0.6
<PackageReference Include="HighPrecisionTimeStamps" Version="1.0.0.6" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add HighPrecisionTimeStamps --version 1.0.0.6
#r "nuget: HighPrecisionTimeStamps, 1.0.0.6"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install HighPrecisionTimeStamps as a Cake Addin
#addin nuget:?package=HighPrecisionTimeStamps&version=1.0.0.6

// Install HighPrecisionTimeStamps as a Cake Tool
#tool nuget:?package=HighPrecisionTimeStamps&version=1.0.0.6

High Precision Timestamps

A utility providing convenient and appropriate alternatives to DateTime.Now.

It is well known that DateTime.Now is often used inappropriately. For example, it may be used together with TimeSpan to produce a task's timeout point or subtracted from another DateTime to calculate a duration. This can cause subtle bugs because DateTime is not monotonic: the system clock can change, making the result of the subtraction inaccurate -- potentially causing a premature timeout or an infinite loop. Yet, DateTime is an incredibly convenient and widely used value type in .NET code and is especially useful when printed in ISO-8601 format (with the "O" format specifier).

With the "O" specifier, you can resolution down to tenths of a microsecond, which is nice. Until you learn that the resolution of the system clock is usually more coarse than several milliseconds, making the additional decimal places misleading garbage values. For calculating durations (time between events), it is better to use a high-resolution and monotonic clock like that provided by System.Diagnostics.Stopwatch: on most computers it is far more accurate than DateTime.Now even though, seemingly paradoxically, on a few systems, its resolution is lower than that of DateTime. Also, unsurprisingly, Stopwatch does not provide values that correlate to times of day: while it is appropriate for calculating durations, it is inappropriate for timestamping against a readable date and time.

This library provides timestamps (both as DateTime and as analogous value types it defines) that use the Stopwatch (and your system's high performance event counter) as its clock, but returns values as DateTimes or an analog thereto so that these values can be used for a mixed purpose of timestamping and providing a meaningful way to calculate time elapsed between events.

It provides Monotonic timestamps and High Resolution timestamps.

High Resolution Timestamps

These timestamps are expressed as DateTime values and are derived from Stopwatch. They are calibrated (correlating a reference tick value of the Stopwatch to a reference time value of the system clock) on a per thread basis and have a calibration window that expires. These are suitable for logging times (in a way meaningful to humans) and can be used to measure the time elapsed between events on a single thread within one calibration window. A calibration window by default lasts for fifteen minutes. Eventually, there will be drift between the system clock and the Stopwatch, making re-calibration necessary. Nevertheless, for the resolution provided by Stopwatch, fifteen minutes should be a sufficient period for the intended use-case of these timestamps. Also, you can always manually trigger a calibration.

Monotonic Timestamps

These use the same source (Stopwatch) for their clock, but calibration happens exactly once per process and is the same across all threads. Thus, you can accurately log the time of events across multiple threads and have meaningful data to compare when events happen. Also, because calibration happens once these values are safe to use to calculate a timeout period, how long to perform a task, etc without the possibility that a change to the system clock can cause a bug. Like the High Resolution Timestamps, their fractional seconds are meaningful on every system I have tested. These are essentially dual-use values: they can be used to log timestamps and to calculate durations or time that your application should spend doing a task before quitting or timing out, etc. The monotonic clock provided returns a value type provided by this library rather than DateTime, though the value type is conveniently convertible into a DateTime. This choice was made because the Stopwatch's frequency can vary between systems and these stamps are intended to be used for calculating and measuring durations in addition to logging: it was desirable not to need to calculate a conversion to and from DateTime/TimeSpan scale when obtaining a stamp or performing a duration calculation. For a similar reason, there is a Duration value type that is to the monotonic stamp what System.TimeSpan is to DateTime: a duration value with a matching frequency.

Example Code

An example code project (available at ExampleCode) is available and used to provide a tour of the functionality and its recommended use-cases. All of the example code below can be found therein. For more elaboration, please consult the full Readme.md in the source repository as it is too long to be displayed on NuGet.

Release Notes

Version 1.0.0.6:

To resolve Issue 24, add Parse and TryParse methods to parse stringified PortableMonotonicTimestamps and PortableDurations. These methods only work with values stringified via the default ToString() methods.

Added unit tests for the methods.

Unit test application now enables the nullable reference type feature.

Version 1.0.0.4:

This release fixes two bugs.

First (see Issue 21), it fixes a bug where using monotonic timestamps close to the extreme values (within a month or so of 1-1-0001AD and 12-31-9999AD) was causing overflow in .NET 5.0. The fix increased the buffer around the min/max values so that overflow does not occur in .NET 5.0. You may have to alter your uses if you were (for some reason) storing portable monotonic stamps close to the extrema of permissible values.

Second (see Issue 22), it fixes a bug where subtracting a portable duration from a portable monotonic stamp was executing addition, not subtraction.

Finally, please note that unit test applications, example code and test application are now all built and run against .NET 5.0 rather than .NET Core 3.1.

Version 1.0.0.2:

This release fixes a bug (see Issue 19) where the PortableDuration type's FromDays factory methods (and perhaps other From factory methods taking a double as a parameter) used incorrect math and incorrect validation logic.

Version 1.0.0.1:

This release contains no changes to the code itself or to program behavior. Instead it merely fixes the repository url to refer to the source repository rather than the http page that hosts the Github repository. Also, it enables the nuget package to be built deterministically.

Version 1.0.0.0:

This is the non-beta release of the fix introduced with beta version 0.1.1.0-beta. The issues resolved by that release included problems with serialization and deserialization of portable monotonic stamps when serialized on a system with a different DateTime.MinValue.ToUniversalTime() value than the one on which it is deserialized. Those changes are discussed in pull request 14, issue 12 and issue 13. The changes to the code can be reviewed in pull request 14, commit x and, most particularly around these lines of code.

Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on HighPrecisionTimeStamps:

Package Downloads
DotNetVault

Synchronization Library and Static Analysis Tool for C# 8 DotNetVault is a library and static code analysis tool that makes managing shared mutable state in multi-threaded applications more manageable and less error prone. It also provides a common abstraction over several commonly used synchronization mechanisms, allowing you to change from one underlying type to another (such as from lock free synchronization to mutex/monitor lock based) without needing to refactor your code. Where errors do still occur, they are easier to locate and identify. The project description (a detailed design document) can be read here: https://github.com/cpsusie/DotNetVault/blob/master/DotNetVault_Description_v1.0.pdf. A quick start guide for installation (Windows, Vs 2019+) can be found here: https://github.com/cpsusie/DotNetVault/blob/v0.2.5.x/QuickStart_Install_VS2019_Windows.md. A quick start guide for installation (Tested on Amazon Linux, Rider 2019.3.1+) can be found here: https://github.com/cpsusie/DotNetVault/blob/v0.2.5.x/Quick_Start_Install_Rider_Amazon_Linux.md. A guided tour / quick start guide for this project's functionality can be found here: https://github.com/cpsusie/DotNetVault/blob/v0.2.5.x/Quick_Start_Functionality_Tour.md

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0.7-beta 87 2/1/2022
1.0.0.6 1,235 10/1/2021
1.0.0.4 167 9/19/2021
1.0.0.2 180 9/4/2021
1.0.0.1 197 8/21/2021
1.0.0 191 8/13/2021
0.1.1-beta 215 8/5/2021
0.1.0 315 12/13/2020
0.0.5.4-beta 219 12/6/2020
0.0.5.1-beta 200 11/27/2020
0.0.4-beta 230 11/18/2020
0.0.3-beta 257 11/15/2020
0.0.2-alpha 178 11/14/2020
0.0.1-alpha 276 1/25/2020

#### Version 1.0.0.6:
     To resolve ([Issue 24][10]), add Parse and TryParse methods to parse stringified PortableMonotonicTimestamps and PortableDurations.  These methods only work with values stringified via the default ToString() methods.

     Added unit tests for the methods.

     Unit test application now enables the nullable reference type feature.

     #### Version 1.0.0.4:
     This release fixes two bugs.

     First (see [Issue 21][8]), it fixes a bug where using monotonic timestamps close to the extreme values (within a month or so of 1-1-0001AD and 12-31-9999AD) was causing overflow in .NET 5.0.  The fix increased the buffer around the min/max values so that overflow does not occur in .NET 5.0.  You may have to alter your uses if you were (for some reason) storing portable monotonic stamps close to the extrema of permissible values.

     Second (see [Issue 22][9]), it fixes a bug where subtracting a portable duration from a portable monotonic stamp was executing addition, not subtraction.

     Finally, please note that unit test applications, example code and test application are now all built and run against .NET 5.0 rather than .NET Core 3.1.
     #### Version 1.0.0.2:
     This release fixes a bug (see [Issue 19][1]) where the PortableDuration type's FromDays factory methods (and perhaps other From factory methods taking a double as a parameter) used incorrect math and incorrect validation logic.

     #### Version 1.0.0.1:
     This release contains no changes to the code itself or to program behavior.  Instead it merely fixes the repository url to refer to the source repository rather than the http page that hosts the Github repository.  Also, it enables the nuget package to be built deterministically.

     #### Version 1.0.0.0:
     This is the non-beta release of the fix introduced with beta version 0.1.1.0-beta.  The issues resolved by that release included problems with serialization and deserialization of portable monotonic stamps when serialized on a system with a different DateTime.MinValue.ToUniversalTime() value than the one on which it is deserialized.  Those changes are discussed in [pull request 14][2], [issue 12][3] and [issue 13][4].  The changes to the code can be reviewed in [pull request 14][2], [commit x][6] and, most particularly around [these lines of code][7].

     [1]: https://github.com/cpsusie/High-Precision-Time-Stamps/issues/19
     [2]: https://github.com/cpsusie/High-Precision-Time-Stamps/pull/14
     [3]: https://github.com/cpsusie/High-Precision-Time-Stamps/issues/12
     [4]: https://github.com/cpsusie/High-Precision-Time-Stamps/issues/13
     [5]: https://github.com/cpsusie/High-Precision-Time-Stamps/pull/14
     [6]: https://github.com/cpsusie/High-Precision-Time-Stamps/commit/01670d88755a4775100f7dd9d09eef61e0775555
     [7]: https://github.com/cpsusie/High-Precision-Time-Stamps/blob/01670d88755a4775100f7dd9d09eef61e0775555/PortableMonotonicStamp.cs#L540
     [8]: https://github.com/cpsusie/High-Precision-Time-Stamps/issues/21
     [9]: https://github.com/cpsusie/High-Precision-Time-Stamps/issues/22
     [10]: https://github.com/cpsusie/High-Precision-Time-Stamps/issues/24