Skip to content

Commit 62c481f

Browse files
committed
std.time: include nano and microseconds in DateTime
1 parent f7b4297 commit 62c481f

File tree

1 file changed

+30
-32
lines changed

1 file changed

+30
-32
lines changed

lib/std/time.zig

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ pub fn localtime(allocator: std.mem.Allocator) LocalTimeError!TimeZone {
8383

8484
/// ISO 8601 compliant date and time representation.
8585
pub const DateTime = struct {
86+
/// nanoseconds, range 0 to 999
87+
nanosecond: u16,
88+
89+
/// microseconds, range 0 to 999
90+
microsecond: u16,
91+
8692
/// milliseconds, range 0 to 999
8793
millisecond: u16,
8894

@@ -110,7 +116,8 @@ pub const DateTime = struct {
110116
/// year, year 0000 is equal to 1 BCE
111117
year: i32,
112118

113-
utc_timestamp: i64,
119+
/// UNIX timestamp in nanoseconds
120+
nano_timestamp: i128,
114121
tt: TimeZone.TimeType,
115122

116123
pub const Weekday = enum(u3) {
@@ -181,7 +188,7 @@ pub const DateTime = struct {
181188

182189
/// Get current date and time in the system's local time.
183190
pub fn now(allocator: std.mem.Allocator) LocalTimeError!DateTime {
184-
const utc_timestamp = timestamp();
191+
const nano_timestamp = nanoTimestamp();
185192

186193
if (builtin.os.tag == .windows) {
187194
var tzi: std.os.windows.TIME_ZONE_INFORMATION = undefined;
@@ -192,7 +199,7 @@ pub const DateTime = struct {
192199
null,
193200
);
194201
if (rc != .SUCCESS) return error.LocalTimeUnavailable;
195-
return fromTimestamp(utc_timestamp, .{
202+
return fromTimestamp(nano_timestamp, .{
196203
.name_data = .{
197204
@intCast(tzi.StandardName[0]),
198205
@intCast(tzi.StandardName[1]),
@@ -207,14 +214,15 @@ pub const DateTime = struct {
207214
}
208215

209216
var sf = std.heap.stackFallback(4096, allocator);
210-
var tz = try localtime(sf.allocator());
211-
defer tz.deinit(sf.allocator());
217+
const sf_allocator = sf.get();
218+
var tz = try localtime(sf_allocator);
219+
defer tz.deinit(sf_allocator);
212220

213-
return fromTimestamp(utc_timestamp, tz.project(utc_timestamp));
221+
return fromTimestamp(nano_timestamp, tz.project(@intCast(@divFloor(nano_timestamp, ns_per_s))));
214222
}
215223

216-
/// Convert timestamp in milliseconds to a DateTime.
217-
pub fn fromTimestamp(utc_timestamp: i64, tt: TimeZone.TimeType) DateTime {
224+
/// Convert UNIX timestamp in nanoseconds to a DateTime.
225+
pub fn fromTimestamp(nano_timestamp: i128, tt: TimeZone.TimeType) DateTime {
218226
// Ported from musl, which is licensed under the MIT license:
219227
// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
220228

@@ -225,7 +233,10 @@ pub const DateTime = struct {
225233
const days_per_100y = 365 * 100 + 24;
226234
const days_per_4y = 365 * 4 + 1;
227235

228-
const seconds = @divTrunc(utc_timestamp, 1000) + tt.offset - leapoch;
236+
const microseconds: i64 = @intCast(@divFloor(nano_timestamp, ns_per_us));
237+
const milliseconds = @divFloor(microseconds, us_per_ms);
238+
239+
const seconds = @divTrunc(milliseconds, ms_per_s) + tt.offset - leapoch;
229240
var days = @divTrunc(seconds, 86400);
230241
var rem_seconds = @as(i32, @truncate(@rem(seconds, 86400)));
231242
if (rem_seconds < 0) {
@@ -290,30 +301,17 @@ pub const DateTime = struct {
290301
.hour = @intCast(@divTrunc(rem_seconds, 3600)),
291302
.minute = @intCast(@rem(@divTrunc(rem_seconds, 60), 60)),
292303
.second = @intCast(@rem(rem_seconds, 60)),
293-
.millisecond = @intCast(@rem(utc_timestamp, 1000)),
294-
.utc_timestamp = utc_timestamp,
304+
.millisecond = @intCast(@rem(milliseconds, 1000)),
305+
.microsecond = @intCast(@rem(microseconds, 1000)),
306+
.nanosecond = @intCast(@rem(nano_timestamp, 1000)),
307+
.nano_timestamp = nano_timestamp,
295308
.tt = tt,
296309
};
297310
}
298311

299312
/// Compare two `DateTime`s.
300313
pub fn order(self: DateTime, other: DateTime) std.math.Order {
301-
var ord = std.math.order(self.year, other.year);
302-
if (ord != .eq) return ord;
303-
304-
ord = std.math.order(self.year_day, other.year_day);
305-
if (ord != .eq) return ord;
306-
307-
ord = std.math.order(self.hour, other.hour);
308-
if (ord != .eq) return ord;
309-
310-
ord = std.math.order(self.minute, other.minute);
311-
if (ord != .eq) return ord;
312-
313-
ord = std.math.order(self.second, other.second);
314-
if (ord != .eq) return ord;
315-
316-
return std.math.order(self.millisecond, other.millisecond);
314+
return std.math.order(self.nano_timestamp, other.nano_timestamp);
317315
}
318316

319317
pub const default_fmt = "%Y-%m-%dT%H%c%M%c%S%z";
@@ -419,7 +417,7 @@ pub const DateTime = struct {
419417
};
420418

421419
test "DateTime basic usage" {
422-
const dt = DateTime.fromTimestamp(1560870105000, TimeZone.TimeType.UTC);
420+
const dt = DateTime.fromTimestamp(1560870105 * ns_per_s, TimeZone.TimeType.UTC);
423421

424422
try testing.expect(dt.second == 45);
425423
try testing.expect(dt.minute == 1);
@@ -432,7 +430,7 @@ test "DateTime basic usage" {
432430
}
433431

434432
test "DateTime.format all" {
435-
const dt = DateTime.fromTimestamp(1560816105000, TimeZone.TimeType.UTC);
433+
const dt = DateTime.fromTimestamp(1560816105 * ns_per_s, TimeZone.TimeType.UTC);
436434
var buf: [100]u8 = undefined;
437435
const result = try std.fmt.bufPrint(&buf, "{%a %A %b %B %m %d %y %Y %I %p %H%c%M%c%S.%s %j %%}", .{dt});
438436
try testing.expectEqualStrings("Tue Tuesday Jun June 06 18 19 2019 12 AM 00:01:45.000 169 %", result);
@@ -444,7 +442,7 @@ test "DateTime.format no format" {
444442
.flags = 0,
445443
.name_data = "EEST\x00\x00".*,
446444
};
447-
const dt = DateTime.fromTimestamp(1560870105000, EEST);
445+
const dt = DateTime.fromTimestamp(1560870105 * ns_per_s, EEST);
448446
var buf: [100]u8 = undefined;
449447
const result = try std.fmt.bufPrint(&buf, "{}", .{dt});
450448
try std.testing.expectEqualStrings("2019-06-18T18:01:45+0300", result);
@@ -469,7 +467,7 @@ pub fn timestamp() i64 {
469467
/// before the epoch.
470468
/// See `std.os.clock_gettime` for a POSIX timestamp.
471469
pub fn milliTimestamp() i64 {
472-
return @as(i64, @intCast(@divFloor(nanoTimestamp(), ns_per_ms)));
470+
return @intCast(@divFloor(nanoTimestamp(), ns_per_ms));
473471
}
474472

475473
/// Get a calendar timestamp, in microseconds, relative to UTC 1970-01-01.
@@ -478,7 +476,7 @@ pub fn milliTimestamp() i64 {
478476
/// before the epoch.
479477
/// See `std.os.clock_gettime` for a POSIX timestamp.
480478
pub fn microTimestamp() i64 {
481-
return @as(i64, @intCast(@divFloor(nanoTimestamp(), ns_per_us)));
479+
return @intCast(@divFloor(nanoTimestamp(), ns_per_us));
482480
}
483481

484482
/// Get a calendar timestamp, in nanoseconds, relative to UTC 1970-01-01.

0 commit comments

Comments
 (0)