const std = @import("std"); const debug = std.debug; const mem = std.mem; const testing = std.testing; const DateTime = @import("main.zig").DateTime; const Year = @import("year.zig").Year; const Month = @import("month.zig").Month; const tz = @import("timezone.zig"); const Offset = tz.Offset; const TimeZone = tz.TimeZone; test "new year" { try testing.expectEqual(Year.new(2023), Year{ .normal = 2023 }); try testing.expectEqual(Year.new(2024), Year{ .leap = 2024 }); } test "get year" { try testing.expectEqual(Year.new(2023).get(), 2023); try testing.expectEqual(Year.new(2024).get(), 2024); } test "next year" { try testing.expectEqual(Year.new(2023).next(), Year{ .leap = 2024 }); } test "last year" { try testing.expectEqual(Year.new(2024).previous(), Year{ .normal = 2023 }); } test "get days in month" { const year = Year.new(2023); const month = Month.february; try testing.expectEqual(month.days(year), 28); } test "next month" { try testing.expectEqual(Month.june.next(), .july); try testing.expectEqual(Month.december.next(), null); } test "last month" { try testing.expectEqual(Month.june.previous(), .may); try testing.expectEqual(Month.january.previous(), null); } test "new offsets" { try testing.expectEqual(Offset.new(-5, null), Offset{ .negative = .{ .hours = 5, .minutes = null } }); try testing.expectEqual(Offset.new(3, null), Offset{ .positive = .{ .hours = 3, .minutes = null } }); } test "as seconds" { try testing.expectEqual(Offset.new(-4, 30).?.asSeconds(), -16200); try testing.expectEqual(Offset.new(3, null).?.asSeconds(), 10800); } test "new timezone" { const zone = TimeZone.new(-5, null).?; try testing.expectEqual(@as(tz.TimeZoneTag, zone), .offset); switch (zone) { .offset => |ofs| try testing.expectEqual(ofs, Offset{ .negative = .{ .hours = 5, .minutes = null } }), else => unreachable, } } test "new timezone utc" { const tz0 = TimeZone.new(null, null).?; const tz1 = TimeZone.new(0, null).?; try testing.expectEqual(@as(tz.TimeZoneTag, tz0), .utc); try testing.expectEqual(@as(tz.TimeZoneTag, tz1), .utc); } test "get year from DateTime" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 12, .hour = 1, .minute = 5, .second = 14, .tz = TimeZone.new(-5, null).?, }; try testing.expectEqual(dt.getYear(), 2023); } test "get offset" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 12, .hour = 1, .minute = 5, .second = 14, .tz = TimeZone.new(-5, null).?, }; try testing.expectEqual(dt.getOffset().?, Offset{ .negative = .{ .hours = 5, .minutes = null } }); } test "to timestamp utc" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 13, .hour = 5, .minute = 21, .second = 22, .tz = .utc, }; try testing.expectEqual(dt.toTimestamp(), 1686633682); } test "to timestamp negative offset" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 13, .hour = 0, .minute = 21, .second = 22, .tz = TimeZone.new(-5, null).?, }; try testing.expectEqual(dt.toTimestamp(), 1686633682); } test "conversions" { const ts = std.time.timestamp(); const dt = DateTime.fromTimestamp(ts); try testing.expectEqual(dt.toTimestamp(), ts); } test "now" { const ts = std.time.timestamp(); const dt = DateTime.now(); try testing.expect(ts <= dt.toTimestamp()); // Make sure they're identical at least to the tens place, since it's possible // for them to vary by a second or more depending on system resources const a = @divTrunc(ts, 10); const b = @divTrunc(dt.toTimestamp(), 10); try testing.expectEqual(a, b); } test "get weekday" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 13, .hour = 6, .minute = 21, .second = 22, .tz = .utc, }; try testing.expectEqual(dt.weekday(), .tuesday); } test "get weekday 2" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 22, .tz = .utc, }; try testing.expectEqual(dt.weekday(), .saturday); } test "ordering lt" { const a = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 22, .tz = .utc, }; const b = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 23, .tz = .utc, }; try testing.expectEqual(a.compare(b), .lt); } test "ordering gt" { const a = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 22, .tz = .utc, }; const b = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 22, .tz = TimeZone.new(1, null).?, }; try testing.expectEqual(a.compare(b), .gt); } test "custom fmt" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 22, .tz = .utc, }; const dt_string = try std.fmt.allocPrint( testing.allocator, "{s}", .{dt}, ); defer testing.allocator.free(dt_string); try testing.expect(mem.eql(u8, dt_string, "2023-06-10T06:21:22Z")); } test "fmt basic" { const dt = DateTime{ .year = Year.new(2023), .month = .june, .day = 10, .hour = 6, .minute = 21, .second = 22, .tz = TimeZone.new(-4, null).?, }; var dt_array = std.ArrayList(u8).init(testing.allocator); defer dt_array.deinit(); var writer = dt_array.writer(); try dt.format_basic(writer); try testing.expect(mem.eql(u8, dt_array.items, "20230610T062122-04")); const dt_string = try std.fmt.allocPrint( testing.allocator, "{s}", .{dt}, ); defer testing.allocator.free(dt_string); try testing.expect(mem.eql(u8, dt_string, "2023-06-10T06:21:22-04")); }