Skip to content

Commit

Permalink
consider negative relative delta
Browse files Browse the repository at this point in the history
  • Loading branch information
FObersteiner committed Nov 7, 2024
1 parent 7fec00a commit 8c71cf1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
19 changes: 11 additions & 8 deletions lib/Datetime.zig
Original file line number Diff line number Diff line change
Expand Up @@ -626,17 +626,20 @@ pub fn addRelative(dt: *const Datetime, rel_delta: Duration.RelativeDelta) !Date
});
var result: Datetime = try dt.add(abs_delta);

// TODO : account for negative rel_delta
const new_month: u8 = @truncate((rel_delta.months + @as(u32, dt.month)) % 12);
result.year += @truncate(rel_delta.years + (rel_delta.months + @as(u32, dt.month)) / 12);
result.month = new_month;
var m_off: i32 = @intCast(rel_delta.months + rel_delta.years * 12);
if (rel_delta.negative) m_off *= -1;
m_off += result.month;

result.year = @intCast(@as(i32, result.year) + @divFloor(m_off, 12));
const new_month: u8 = @intCast(@mod(m_off, 12));
if (new_month <= 0) {
result.month = new_month + 12;
result.year -= 1;
} else result.month = new_month;

const days_in_month = cal.daysInMonth(result.month, cal.isLeapYear(result.year));
if (result.day > days_in_month) result.day = days_in_month;

const opts: ?tz_options = if (dt.tz) |tz_ptr| .{ .tz = tz_ptr } else null;

// TODO : 'normalizeTOFields'
return try Datetime.fromFields(.{
.year = result.year,
.month = result.month,
Expand All @@ -646,7 +649,7 @@ pub fn addRelative(dt: *const Datetime, rel_delta: Duration.RelativeDelta) !Date
.second = result.second,
.nanosecond = result.nanosecond,
.dst_fold = result.dst_fold,
.tz_options = opts,
.tz_options = if (dt.tz) |tz_ptr| .{ .tz = tz_ptr } else null,
});
}

Expand Down
22 changes: 20 additions & 2 deletions tests/test_duration.zig
Original file line number Diff line number Diff line change
Expand Up @@ -414,12 +414,30 @@ test "add relative delta to datetime" {
.datetime_b = try Datetime.fromFields(.{ .year = 1971, .month = 2 }),
.rel_delta = .{ .years = 1, .months = 1 },
},
.{
.datetime_a = try Datetime.fromFields(.{ .year = 1970 }),
.datetime_b = try Datetime.fromFields(.{ .year = 1969, .month = 11 }),
.rel_delta = .{ .months = 2, .negative = true },
},
.{
.datetime_a = try Datetime.fromFields(.{ .year = 1970, .day = 31 }),
.datetime_b = try Datetime.fromFields(.{ .year = 1970, .month = 2, .day = 28 }),
.rel_delta = .{ .months = 1 },
},
.{
.datetime_a = try Datetime.fromFields(.{ .year = 1970, .month = 1, .day = 31 }),
.datetime_b = try Datetime.fromFields(.{ .year = 1968, .month = 12, .day = 31 }),
.rel_delta = .{ .months = 13, .negative = true },
},
.{
.datetime_a = try Datetime.fromFields(.{ .year = 1970, .month = 1, .day = 31 }),
.datetime_b = try Datetime.fromFields(.{ .year = 1965, .month = 11, .day = 30 }),
.rel_delta = .{ .years = 3, .months = 14, .negative = true },
},
};

for (cases) |case| {
const dt_new = try case.datetime_a.addRelative(case.rel_delta);
log.warn("old: {s}, want {s}", .{ case.datetime_a, case.datetime_b });
log.warn("new: {s}", .{dt_new});
try testing.expectEqual(case.datetime_b, dt_new);
}
}

0 comments on commit 8c71cf1

Please sign in to comment.