@@ -83,6 +83,12 @@ pub fn localtime(allocator: std.mem.Allocator) LocalTimeError!TimeZone {
8383
8484/// ISO 8601 compliant date and time representation.
8585pub 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
421419test "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
434432test "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.
471469pub 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.
480478pub 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