Zeit: a date time library

Zeit (German for “time”) is a date time library with basic batteries included:

  • Zero dependency :muscle:
  • Timezone aware. TZDB, POSIX, fixed offsets, and Windows DynamicTimeZones
  • DST support
  • Leap-second handling
  • Parse from ISO8601/RFC3339
  • Format with strftime specifiers or Golang magic dates
  • Exported via build.zig so you can use at build time

The API is somewhat similar to go’s time package, though it’s intentionally a very small API.

Sample usage (from the README):

const std = @import("std");
const zeit = @import("zeit");

pub fn main() void {
    const allocator = std.heap.page_allocator;
    var env = try std.process.getEnvMap(allocator);
    defer env.deinit();

    // Get an instant in time. The default gets "now" in UTC
    const now = zeit.instant(.{});

    // Load our local timezone. This needs an allocator. Optionally pass in a
    // *const std.process.EnvMap to support TZ and TZDIR environment variables
    const local = zeit.local(alloc, &env);

    // Convert our instant to a new timezone
    const now_local = now.in(&local);

    // Generate date/time info for this instant
    const dt = now_local.time();

    // Print it out
    std.debug.print("{}", .{dt});

    // zeit.Time{
    //    .year = 2024,
    //    .month = zeit.Month.mar,
    //    .day = 16,
    //    .hour = 8,
    //    .minute = 38,
    //    .second = 29,
    //    .millisecond = 496,
    //    .microsecond = 706,
    //    .nanosecond = 64
    //    .offset = -18000,
    // }

    // Format using strftime specifier. Format strings are not required to be comptime
    try dt.strftime(anywriter, "%Y-%m-%d %H:%M:%S %Z");

    // Or...golang magic date specifiers. Format strings are not required to be comptime
    try dt.gofmt(anywriter, "2006-01-02 15:04:05 MST");

    // Load an arbitrary location using IANA location syntax. The location name
    // comes from an enum which will automatically map IANA location names to
    // Windows names, as needed. Pass an optional EnvMap to support TZDIR
    const vienna = zeit.loadTimeZone(alloc, .@"Europe/Vienna", &env);
    defer vienna.deinit();

    // Parse an Instant from an ISO8601 or RFC3339 string
    const iso = zeit.instant(.{
	.source = .{
	    .iso8601 = "2024-03-16T08:38:29.496-1200",
	},
    });

    const rfc3339 = zeit.instant(.{
	.source = .{
	    .rfc3339 = "2024-03-16T08:38:29.496706064-1200",
	},
    });
22 Likes

This is great, thanks!

1 Like

I first stumbled upon Zeit when searching for a simple time library for the Zig programming language. It instantly clicked for me because it parsed times in common formats and was very accessible to use. I could more or less grasp the code even as a newcomer to the language.

It implements most if not all of the functionality I’ll ever need when dealing with times and the performance feels great. I appreciate how it doesn’t require any dependencies outside std.

Recently I opened a couple of PRs with my small contributions. The author quickly reviewed them and accepted my code, confirming how nice and welcoming the Zig community is.

Thank you @rockorager for this library.

6 Likes

I finally got around to implementing this in my little time tracking tool trecker. Finally, my times are based on the correct time zone :slight_smile: