MinimalTime 0.2.0-beta.2
dotnet add package MinimalTime --version 0.2.0-beta.2
NuGet\Install-Package MinimalTime -Version 0.2.0-beta.2
<PackageReference Include="MinimalTime" Version="0.2.0-beta.2" />
<PackageVersion Include="MinimalTime" Version="0.2.0-beta.2" />
<PackageReference Include="MinimalTime" />
paket add MinimalTime --version 0.2.0-beta.2
#r "nuget: MinimalTime, 0.2.0-beta.2"
#:package MinimalTime@0.2.0-beta.2
#addin nuget:?package=MinimalTime&version=0.2.0-beta.2&prerelease
#tool nuget:?package=MinimalTime&version=0.2.0-beta.2&prerelease
MinimalTime
A minimal time library for .NET. Safe, small, and unambiguous.
MinimalTime.Zulu
The primary type in the library is Zulu — a value type that represents an instant in UTC.
Zulu in intended to be used in a similar way to DateTime/DateTimeOffset, in systems that use UTC internally.
Zulu.Parse(string), Zulu.ToString() and JSON serialization/deserialization of types with Zulu properties all use a single, simple, compact format without delimiters, time zone information or redundant trailing characters. The format is called Zulu Compact Format (ZCF), and like this library, it is intended to represent UTC instants only.
ZCF is similar to ISO 8601 Basic, but without the 'T' or any other delimiter, and without time zone information, since the format only represents UTC.
A ZCF string is a contiguous digit-only string that encodes a UTC instant with progressively finer precision.
Allowed lengths and meanings
| Length | Format | Meaning | Zulu example | ISO (UTC) example |
|---|---|---|---|---|
| 4 | YYYY | Year | "2025" | 2025-01-01T00:00:00Z |
| 6 | YYYYMM | Year → month | "202503" | 2025-03-01T00:00:00Z |
| 8 | YYYYMMDD | Year → day | "20250306" | 2025-03-06T00:00:00Z |
| 10 | YYYYMMDDHH | Year → hour | "2025030614" | 2025-03-06T14:00:00Z |
| 12 | YYYYMMDDHHmm | Year → minute | "202503061430" | 2025-03-06T14:30:00Z |
| 14 | YYYYMMDDHHmmss | Year → second | "20250306143015" | 2025-03-06T14:30:15Z |
| 17 | YYYYMMDDHHmmssfff | Year → ms | "20250306143015999" | 2025-03-06T14:30:15.999Z |
Defaults for any omitted trailing parts:
- Month = 1, Day = 1, Hour = 0, Minute = 0, Second = 0, Millisecond = 0.
Compared to other common formats, ZCF is more compact, easier to parse, and avoids ambiguity by representing only UTC times.
The space savings are significant when storing multiple timestamps, for example in JSON files.
Comparison with other common formats
| Format | Example | Length |
|---|---|---|
| ISO 8601, ToString("o") | 2025-03-01T00:00:00.0000000+00:00 | 33 |
| ISO 8601, millisecond precision | 2025-03-06T14:30:15.999Z | 24 |
| ISO 8601, second precision | 2025-03-06T14:30:15Z | 20 |
| Universal sortable, ToString("u") | 2025-03-06 14:30:15Z | 20 |
| Zulu Compact Format, millisecond precision | 20250306143015999 | 17 |
| Zulu Compact Format, minute precision | 202503061430 | 12 |
| Zulu Compact Format, hour precision | 2025030614 | 10 |
| Zulu Compact Format, day precision | 20250306 | 8 |
ZCF is big-endian and lexically sortable.
Why only UTC?
- One timeline: avoids DST/offset ambiguity and makes comparisons deterministic.
- Convert at the edges: normalize incoming local/offset times to UTC on input; convert back only for display.
- Compact payloads: no offset/zone data, no redundant trailing characters, fixed sizes for time parts, no delimiters, smaller JSON.
- Interop is explicit: use DateTime/DateTimeOffset for conversions; MinimalTime enforces UTC to prevent accidental local-time use.
with simple interop and a compact format for string handling and serialization.
Features
- Type: MinimalTime.Zulu (record struct)
- Format:
YYYY[MM[DD[HH[mm[ss[fff]]]]]](no separators; only up to last non-default part) - Defaults: Year=1, Month=1, Day=1, Hour=0, Minute=0, Second=0, Millisecond=0
- Interop: To/From UTC DateTime and DateTimeOffset
- Built-in System.Text.Json converter
- Ergonomics: int-friendly factories
Zulu.FromParts(int …)andZulu.FromParts(params int[]) - Targets: .NET 8 or later.
Install
Pre-release (API may change):
dotnet add package MinimalTime --version 0.2.0-beta.2
Quick start
using System;
using System.Text.Json;
using MinimalTime;
// Construct
var z1 = new Zulu(2024); // ToString() => "2024"
var z2 = new Zulu(2024, 2, 3, 4, 5); // ToString() => "202402030405"
// Int-friendly construction (variables)
int year = 2024, month = 8, day = 14, hour = 7;
var zVar = Zulu.FromParts(year, month, day, hour); // "2024081407"
// Parse
var z3 = Zulu.Parse("202402030405");
// Convert to BCL types (UTC)
DateTime dt = z2.DateTime(); // Kind = Utc
DateTimeOffset dto = z2.DateTimeOffset(); // Offset = +00:00
// From UTC BCL types (throws if not UTC)
var z4 = new DateTime(2025, 1, 2, 0, 0, 0, DateTimeKind.Utc).Zulu();
var z5 = new DateTimeOffset(2025, 1, 2, 0, 0, 0, TimeSpan.Zero).Zulu();
// Arithmetic
var later = z2 + TimeSpan.FromMinutes(30);
bool isAfter = later > z2;
// JSON
string json = JsonSerializer.Serialize(z2); // -> "202402030405"
var roundtrip = JsonSerializer.Deserialize<Zulu>(json)!;
Boundary recipes
Convert incoming local/offset time to Zulu (UTC):
using MinimalTime;
// Prefer DateTimeOffset (it carries an offset)
DateTimeOffset local = DateTimeOffset.Now;
Zulu utc = local.ToUniversalTime().Zulu();
// If you only have DateTime, ensure it's actually UTC before converting
DateTime utcDt = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local).ToUniversalTime();
Zulu z = utcDt.Zulu();
Convert back for display with a user's offset/zone:
Zulu z = new(2024, 2, 3, 4, 5);
DateTimeOffset utc = z.DateTimeOffset();
// Fixed offset (e.g., profile setting)
var view = utc.ToOffset(TimeSpan.FromHours(-5));
// Time zone conversion
var tz = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
var localView = TimeZoneInfo.ConvertTime(utc, tz);
Notes:
- Extensions throw if inputs aren't UTC (DateTime.Kind != Utc or DateTimeOffset.Offset != TimeSpan.Zero).
JSON serialization (System.Text.Json)
Zulu has a built-in converter and serializes to a single string value.
using System.Text.Json;
using MinimalTime;
var z = new Zulu(2024, 2, 3, 4, 5);
string json = JsonSerializer.Serialize(z); // "\"202402030405\""
var roundtrip = JsonSerializer.Deserialize<Zulu>(json);
Validation and ranges
- Valid ranges: Year 1–9999; Month 1–12; Day 1–31; Hour 0–23; Minute/Second 0–59; Millisecond 0–999.
- Invalid inputs throw ArgumentOutOfRangeException.
- Conversions from DateTime/DateTimeOffset require UTC (
Kind == Utc/Offset == TimeSpan.Zero), otherwise ArgumentException.
API surface
- Type: MinimalTime.Zulu (record struct)
- Properties: Year, Month, Day, Hour, Minute, Second, Millisecond
- Methods: ToString(), Parse(string), CompareTo(Zulu)
- Operators:
-(TimeSpan),+(TimeSpan),>,< - Static:
Zulu.Min,Zulu.Max,Zulu.FromParts(int …),Zulu.FromParts(params int[]) - Extensions:
Zulu.DateTime(),Zulu.DateTimeOffset(),DateTime.Zulu(),DateTimeOffset.Zulu()
Compactness
- ISO
2025-01-01T00:00:00Z(20) → "2025" (4) - ISO
2025-08-14T07:00:00Z(20) → "2025081407" (10)
Notes
- UTC-only. Conversions from non-UTC DateTime/DateTimeOffset throw.
- For display in other time zones, convert to DateTimeOffset and adjust.
- Valid ranges: Year 1–9999; Month 1–12; Day 1–31; Hour 0–23; Minute/Second 0–59; Millisecond 0–999.
- The public type uses ushort for compact storage and is marked [CLSCompliant(false)]. Use the int-friendly factories for convenient construction from int variables.
Zulu Compact Format (ZCF)
- Format: YYYY[MM[DD[HH[mm[ss[fff]]]]]] (digits only, zero‑padded; no 'T' or zone suffix).
- Semantics: single‑zone timestamps; this library uses UTC and enforces UTC on conversions.
- Allowed lengths: 4, 6, 8, 10, 12, 14, 17.
- Defaults for omitted trailing parts: Month=1, Day=1, Hour=0, Minute=0, Second=0, Millisecond=0.
- Examples: "2025", "20250814", "2025081407", "20250814073015999".
- Note: not a strict ISO 8601 combined datetime because it omits the 'T' and any zone suffix.
License
MIT — see LICENSE.txt.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|