@@ -112,7 +112,9 @@ pub const DateTime = struct {
112112
113113 /// UNIX timestamp in nanoseconds
114114 nano_timestamp : i128 ,
115- tt : TimeZone.TimeType ,
115+
116+ /// The time zone to which `nano_timestamp` was projected to.
117+ tz_projection : TimeZone.Projection ,
116118
117119 pub const Weekday = enum (u3 ) {
118120 monday = 1 ,
@@ -181,6 +183,9 @@ pub const DateTime = struct {
181183 };
182184
183185 /// Get current date and time in the system's local time.
186+ /// On non-Windows systems this loads the system's local time
187+ /// time zone database from the filesystem and may allocate
188+ /// so when called repeated `nowTz` should be preferred.
184189 pub fn now (allocator : std.mem.Allocator ) LocalTimeError ! DateTime {
185190 const nano_timestamp = nanoTimestamp ();
186191
@@ -202,7 +207,6 @@ pub const DateTime = struct {
202207 @intCast (tzi .StandardName [4 ]),
203208 @intCast (tzi .StandardName [5 ]),
204209 },
205- .flags = 0 ,
206210 .offset = tzi .Bias ,
207211 });
208212 }
@@ -215,8 +219,13 @@ pub const DateTime = struct {
215219 return fromTimestamp (nano_timestamp , tz .project (@intCast (@divFloor (nano_timestamp , ns_per_s ))));
216220 }
217221
222+ pub fn nowTz (tz : * const TimeZone ) DateTime {
223+ const nano_timestamp = nanoTimestamp ();
224+ return fromTimestamp (nano_timestamp , tz .project (@intCast (@divFloor (nano_timestamp , ns_per_s ))));
225+ }
226+
218227 /// Convert UNIX timestamp in nanoseconds to a DateTime.
219- pub fn fromTimestamp (nano_timestamp : i128 , tt : TimeZone.TimeType ) DateTime {
228+ pub fn fromTimestamp (nano_timestamp : i128 , tz_projection : TimeZone.Projection ) DateTime {
220229 // Ported from musl, which is licensed under the MIT license:
221230 // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
222231
@@ -228,7 +237,7 @@ pub const DateTime = struct {
228237 const days_per_4y = 365 * 4 + 1 ;
229238
230239 const seconds_unadjusted : i64 = @intCast (@divFloor (nano_timestamp , ns_per_s ));
231- const seconds = seconds_unadjusted + tt .offset - leapoch ;
240+ const seconds = seconds_unadjusted + tz_projection .offset - leapoch ;
232241 var days = @divTrunc (seconds , 86400 );
233242 var rem_seconds = @as (i32 , @truncate (@rem (seconds , 86400 )));
234243 if (rem_seconds < 0 ) {
@@ -295,7 +304,7 @@ pub const DateTime = struct {
295304 .second = @intCast (@rem (rem_seconds , 60 )),
296305 .nanosecond = @intCast (@rem (nano_timestamp , ns_per_s )),
297306 .nano_timestamp = nano_timestamp ,
298- .tt = tt ,
307+ .tz_projection = tz_projection ,
299308 };
300309 }
301310
@@ -372,7 +381,7 @@ pub const DateTime = struct {
372381 'H' = > try std .fmt .formatInt (date .hour , 10 , .lower , .{ .width = 2 , .fill = '0' }, writer ),
373382 'M' = > try std .fmt .formatInt (date .minute , 10 , .lower , .{ .width = 2 , .fill = '0' }, writer ),
374383 'S' = > try std .fmt .formatInt (date .second , 10 , .lower , .{ .width = 2 , .fill = '0' }, writer ),
375- 's' = > try std .fmt .formatInt (date .millisecond , 10 , .lower , .{ .width = 3 , .fill = '0' }, writer ),
384+ 's' = > try std .fmt .formatInt (@divFloor ( date .nanosecond , ns_per_ms ) , 10 , .lower , .{ .width = 3 , .fill = '0' }, writer ),
376385 'j' = > try std .fmt .formatInt (date .year_day , 10 , .lower , .{ .width = 3 , .fill = '0' }, writer ),
377386 'p' = > if (date .hour < 12 ) {
378387 try writer .writeAll ("AM" );
@@ -384,15 +393,15 @@ pub const DateTime = struct {
384393 begin = i + 1 ;
385394 },
386395 'z' = > {
387- const sign = "+-" [@intFromBool (date .tt .offset < 0 )];
396+ const sign = "+-" [@intFromBool (date .tz_projection .offset < 0 )];
388397 try writer .writeByte (sign );
389- const abs = @abs (date .tt .offset );
398+ const abs = @abs (date .tz_projection .offset );
390399 const hours = @divFloor (abs , 3600 );
391400 const minutes = @rem (@divFloor (abs , 60 ), 60 );
392401 try std .fmt .formatInt (hours , 10 , .lower , .{ .width = 2 , .fill = '0' }, writer );
393402 try std .fmt .formatInt (minutes , 10 , .lower , .{ .width = 2 , .fill = '0' }, writer );
394403 },
395- 'Z' = > try writer .writeAll (date .tt .name ()),
404+ 'Z' = > try writer .writeAll (date .tz_projection .name ()),
396405 else = > @compileError ("Unknown format character: " ++ [_ ]u8 {fmt [i ]}),
397406 }
398407 }
@@ -406,8 +415,13 @@ pub const DateTime = struct {
406415 }
407416};
408417
418+ const null_projection : TimeZone.Projection = .{
419+ .offset = 0 ,
420+ .name_data = "TEST\x00\x00 " .* ,
421+ };
422+
409423test "DateTime basic usage" {
410- const dt = DateTime .fromTimestamp (1560870105 * ns_per_s , TimeZone . TimeType . UTC );
424+ const dt = DateTime .fromTimestamp (1560870105 * ns_per_s , null_projection );
411425
412426 try testing .expect (dt .second == 45 );
413427 try testing .expect (dt .minute == 1 );
@@ -420,16 +434,15 @@ test "DateTime basic usage" {
420434}
421435
422436test "DateTime.format all" {
423- const dt = DateTime .fromTimestamp (1560816105 * ns_per_s , TimeZone . TimeType . UTC );
437+ const dt = DateTime .fromTimestamp (1560816105 * ns_per_s , null_projection );
424438 var buf : [100 ]u8 = undefined ;
425439 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 });
426440 try testing .expectEqualStrings ("Tue Tuesday Jun June 06 18 19 2019 12 AM 00:01:45.000 169 %" , result );
427441}
428442
429443test "DateTime.format no format" {
430- const EEST : TimeZone.TimeType = .{
444+ const EEST : TimeZone.Projection = .{
431445 .offset = 10800 ,
432- .flags = 0 ,
433446 .name_data = "EEST\x00\x00 " .* ,
434447 };
435448 const dt = DateTime .fromTimestamp (1560870105 * ns_per_s , EEST );
0 commit comments