# Simple timestamp lib to record timestamp in logs with millisecond precision

**URL:** <https://ziggit.dev/t/simple-timestamp-lib-to-record-timestamp-in-logs-with-millisecond-precision/13658>\
**Category:** Showcase\
**Tags:** language\
**Created:** [December 25, 2025, 3:29pm UTC](https://ziggit.dev/t/simple-timestamp-lib-to-record-timestamp-in-logs-with-millisecond-precision/13658 "2025-12-25T15:29:20Z")\
**Posts on this page:** 1\
**Showing post:** 8

<div class="post-metadata">

**Author:** ![Sze](https://ziggit.dev/user_avatar/ziggit.dev/sze/32/496_2.png) [@Sze](https://ziggit.dev/u/Sze)\
**Post date:** [January 13, 2026, 6:36pm UTC](https://ziggit.dev/t/simple-timestamp-lib-to-record-timestamp-in-logs-with-millisecond-precision/13658/8 "2026-01-13T18:36:26Z")

</div>

Reminds me a bit of this topic:

> [@Format timestamp into ISO 8601 strings](https://ziggit.dev/t/format-timestamp-into-iso-8601-strings/3824):
>
> I’m surprised that it’s not in the standard library. I know of a few Zig datetime libraries but sometimes all you want is to dump the current time as ISO 8601. So, I wanted to share this snippet in case anyone was interested. Look for TimeParts below for the formatting code. Features: Format a millisecond timestamp from std.time.milliTimestamp(). No allocation. A packed struct of only 48 bits yet still loosely aligned on 8-bit byte boundary. Can format geographical timezones (i.e., merely shi…

* * *

@miagi Personally I think it would be better to use format functions and write the output directly to a writer, also I don’t like the baked in panic everywhere, I think it would be better to return the error and then let the user/call-site decide whether they want to panic. (And document that those functions could panic)

I think for application code it is fine to decide to panic, but in library code I would try to avoid it or at least keep the number of places that could panic lower, for example by having an error-ing version and another versions that panics and just wraps the error version (if it seems appropriate to provide a panic-ing one at all).

Also it makes sense to statically prove the absense of errors for certain inputs through exhaustive testing, because `check_decimal(u6, ...)` will never result in `error.NoSpaceLeft`, because it is impossible to provide a value that would cause that error, so basically I think it would make sense to use more specialized functions here that are proven via tests or assertions to not fail and thus don’t need to return an error. (Which also removes the need for the repeated `catch panic`)

Additionally there is already a `digit2` function in the standard library so we can use that one when size is 2. So here is a sketch of what I am thinking of:

```zig
const std = @import("std");

fn safeDecimal(size: comptime_int, comptime T: type, in: T) [size]u8 {
    const fmt = "{[value]d:0>[size]}";
    comptime std.debug.assert(std.fmt.count(fmt, .{ .value = std.math.maxInt(T), .size = size }) <= size);
    if (comptime size == 2) return std.fmt.digits2(in);
    var b: [size]u8 = undefined;
    _ = std.fmt.bufPrint(&b, fmt, .{ .value = in, .size = size }) catch unreachable;
    return b;
}

fn testHelper(size: comptime_int, comptime T: type) void {
    for (0..std.math.maxInt(T)) |i| {
        _ = safeDecimal(size, T, @intCast(i));
    }
}

test {
    testHelper(1, u1);
    testHelper(1, u2);
    testHelper(1, u3);
    testHelper(2, u4);
    testHelper(2, u5);
    testHelper(2, u6);
    testHelper(3, u7);
    testHelper(3, u8);
    testHelper(3, u9);
    testHelper(4, u10);
}

```

An additional improvement could be to calculate the highest type of all types that fit in a certain size and then use that one’s specialization for all in that size-group (to save on the number of generated type specializations and save on code size).

---

_[View the full topic](https://ziggit.dev/t/simple-timestamp-lib-to-record-timestamp-in-logs-with-millisecond-precision/13658)._
