118 lines
4.9 KiB
Zig
118 lines
4.9 KiB
Zig
const std = @import("std");
|
|
const log = std.log.scoped(.date);
|
|
const zeit = @import("zeit");
|
|
|
|
pub const DateTime = struct {
|
|
day: u8,
|
|
month: u8,
|
|
year: u16,
|
|
hour: u8,
|
|
minute: u8,
|
|
second: u8,
|
|
|
|
pub fn fromInstant(val: zeit.Instant) DateTime {
|
|
return fromTime(val.time());
|
|
}
|
|
|
|
pub fn fromTime(val: zeit.Time) DateTime {
|
|
return DateTime{
|
|
.day = val.day,
|
|
.month = @intFromEnum(val.month),
|
|
.year = @intCast(val.year),
|
|
.hour = val.hour,
|
|
.minute = val.minute,
|
|
.second = val.second,
|
|
};
|
|
}
|
|
|
|
pub fn time(self: DateTime) zeit.Time {
|
|
return zeit.Time{
|
|
.day = @intCast(self.day),
|
|
.month = @enumFromInt(self.month),
|
|
.year = self.year,
|
|
.hour = @intCast(self.hour),
|
|
.minute = @intCast(self.minute),
|
|
.second = @intCast(self.second),
|
|
};
|
|
}
|
|
|
|
pub fn instant(self: DateTime) !zeit.Instant {
|
|
return try zeit.instant(.{ .source = .{ .time = self.time() } });
|
|
}
|
|
};
|
|
|
|
pub fn timestampToDateTime(timestamp: zeit.Seconds) DateTime {
|
|
const ins = zeit.instant(.{ .source = .{ .unix_timestamp = timestamp } }) catch @panic("Failed to create instant from timestamp");
|
|
return DateTime.fromInstant(ins);
|
|
}
|
|
|
|
pub fn parseEnglishToTimestamp(data: []const u8) !i64 {
|
|
return try dateTimeToTimestamp(try parseEnglishToDateTime(data));
|
|
}
|
|
|
|
/// Converts a string to a timestamp value. May not handle dates before the
|
|
/// epoch. Dates should look like "Fri, 03 Jun 2022 18:12:36 GMT"
|
|
pub fn parseEnglishToDateTime(data: []const u8) !DateTime {
|
|
const ins = try zeit.instant(.{ .source = .{ .rfc1123 = data } });
|
|
return DateTime.fromInstant(ins);
|
|
}
|
|
|
|
pub fn parseIso8601ToTimestamp(data: []const u8) !i64 {
|
|
return try dateTimeToTimestamp(try parseIso8601ToDateTime(data));
|
|
}
|
|
|
|
/// Converts a string to a timestamp value. May not handle dates before the
|
|
/// epoch
|
|
pub fn parseIso8601ToDateTime(data: []const u8) !DateTime {
|
|
const ins = try zeit.instant(.{ .source = .{ .iso8601 = data } });
|
|
return DateTime.fromInstant(ins);
|
|
}
|
|
|
|
pub fn dateTimeToTimestamp(datetime: DateTime) !zeit.Seconds {
|
|
return (try datetime.instant()).unixTimestamp();
|
|
}
|
|
|
|
fn printDateTime(dt: DateTime) void {
|
|
log.debug("{:0>4}-{:0>2}-{:0>2}T{:0>2}:{:0>2}:{:0<2}Z", .{
|
|
dt.year,
|
|
dt.month,
|
|
dt.day,
|
|
dt.hour,
|
|
dt.minute,
|
|
dt.second,
|
|
});
|
|
}
|
|
|
|
pub fn printNowUtc() void {
|
|
printDateTime(timestampToDateTime(std.time.timestamp()));
|
|
}
|
|
|
|
test "Convert timestamp to datetime" {
|
|
printDateTime(timestampToDateTime(std.time.timestamp()));
|
|
try std.testing.expectEqual(DateTime{ .year = 2020, .month = 8, .day = 28, .hour = 9, .minute = 32, .second = 27 }, timestampToDateTime(1598607147));
|
|
|
|
try std.testing.expectEqual(DateTime{ .year = 2020, .month = 11, .day = 1, .hour = 5, .minute = 6, .second = 7 }, timestampToDateTime(1604207167));
|
|
// Get time for date: https://wtools.io/convert-date-time-to-unix-time
|
|
try std.testing.expectEqual(DateTime{ .year = 2015, .month = 8, .day = 30, .hour = 12, .minute = 36, .second = 0 }, timestampToDateTime(1440938160));
|
|
}
|
|
|
|
test "Convert datetime to timestamp" {
|
|
try std.testing.expectEqual(@as(i64, 1598607147), try dateTimeToTimestamp(DateTime{ .year = 2020, .month = 8, .day = 28, .hour = 9, .minute = 32, .second = 27 }));
|
|
try std.testing.expectEqual(@as(i64, 1604207167), try dateTimeToTimestamp(DateTime{ .year = 2020, .month = 11, .day = 1, .hour = 5, .minute = 6, .second = 7 }));
|
|
try std.testing.expectEqual(@as(i64, 1440938160), try dateTimeToTimestamp(DateTime{ .year = 2015, .month = 8, .day = 30, .hour = 12, .minute = 36, .second = 0 }));
|
|
}
|
|
|
|
test "Convert ISO8601 string to timestamp" {
|
|
try std.testing.expectEqual(DateTime{ .year = 2020, .month = 8, .day = 28, .hour = 9, .minute = 32, .second = 27 }, try parseIso8601ToDateTime("20200828T093227"));
|
|
try std.testing.expectEqual(DateTime{ .year = 2020, .month = 8, .day = 28, .hour = 9, .minute = 32, .second = 27 }, try parseIso8601ToDateTime("2020-08-28T9:32:27Z"));
|
|
try std.testing.expectEqual(DateTime{ .year = 2020, .month = 11, .day = 1, .hour = 5, .minute = 6, .second = 7 }, try parseIso8601ToDateTime("2020-11-01T5:06:7Z"));
|
|
try std.testing.expectEqual(DateTime{ .year = 2015, .month = 8, .day = 30, .hour = 12, .minute = 36, .second = 0 }, try parseIso8601ToDateTime("2015-08-30T12:36:00.000Z"));
|
|
}
|
|
test "Convert datetime to timestamp before 1970" {
|
|
try std.testing.expectEqual(@as(i64, -449392815), try dateTimeToTimestamp(DateTime{ .year = 1955, .month = 10, .day = 5, .hour = 16, .minute = 39, .second = 45 }));
|
|
}
|
|
|
|
test "Convert whatever AWS is sending us to timestamp" {
|
|
const string_date = "Fri, 03 Jun 2022 18:12:36 GMT";
|
|
try std.testing.expectEqual(DateTime{ .year = 2022, .month = 6, .day = 3, .hour = 18, .minute = 12, .second = 36 }, try parseEnglishToDateTime(string_date));
|
|
}
|