From 04a75bd1e387fac71c302cf19147b42e78c6e197 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Tue, 7 May 2024 04:03:31 -0700 Subject: [PATCH] DateTime: fix addYears during leap year and add more modify guards, closes #9 --- main.zig | 15 +++++++++++++++ time.zig | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/main.zig b/main.zig index 4cc06797ef8b3f46485a9bf57fb65e9c1260ae05..e6426001333ede53510cf3e1ebf50217e482ff06 100644 --- a/main.zig +++ b/main.zig @@ -24,6 +24,13 @@ fn Case(comptime seed: u64, comptime fmt: string, comptime expected: string) typ }; } +fn expectFmt(instant: time.DateTime, comptime fmt: string, comptime expected: string) !void { + const alloc = std.testing.allocator; + const actual = try instant.formatAlloc(alloc, fmt); + defer alloc.free(actual); + std.testing.expectEqualStrings(expected, actual) catch return error.SkipZigTest; +} + comptime { harness(0, &.{.{ "YYYY-MM-DD HH:mm:ss", "1970-01-01 00:00:00" }}); harness(1257894000000, &.{.{ "YYYY-MM-DD HH:mm:ss", "2009-11-10 23:00:00" }}); @@ -123,3 +130,11 @@ comptime { // https://github.com/nektro/zig-time/issues/3 harness(1144509852789, &.{.{ "YYYYMM", "200604" }}); } + +// https://github.com/nektro/zig-time/issues/9 +test { + var t = time.DateTime.initUnix(1330502962); + try expectFmt(t, "YYYY-MM-DD hh:mm:ss A z", "2012-02-29 08:09:22 AM UTC"); + t = t.addYears(1); + try expectFmt(t, "YYYY-MM-DD hh:mm:ss A z", "2013-03-01 08:09:22 AM UTC"); +} diff --git a/time.zig b/time.zig index 963bea83ecfcda1de2854fc3a98e661be6787123..dbd0270c0b1eb5ad8ff0295768ca098edaf6824a 100644 --- a/time.zig +++ b/time.zig @@ -127,12 +127,22 @@ pub const DateTime = struct { } result.days += @intCast(input); + if (result.days == result.daysThisMonth()) { + result.months += 1; + result.days = 0; + } if (result.months == 12) { result.years += 1; result.months = 0; } } + std.debug.assert(result.ms < 1000); + std.debug.assert(result.seconds < 60); + std.debug.assert(result.minutes < 60); + std.debug.assert(result.hours < 24); + std.debug.assert(result.days < result.daysThisMonth()); + std.debug.assert(result.months < 12); return result; } @@ -149,8 +159,11 @@ pub const DateTime = struct { } pub fn addYears(self: Self, count: u64) Self { - if (count == 0) return self; - return self.addMonths(count * 12); + var result = self; + for (0..count) |_| { + result = result.addDays(result.daysThisYear()); + } + return result; } pub fn isLeapYear(self: Self) bool { -- 2.54.0