add parameter --time

You can not generate a code for a specific time. Currently only UTC is
supported.
This commit is contained in:
2025-03-09 20:19:45 +01:00
parent ff7d1ede59
commit f5f1e1593b
2 changed files with 160 additions and 70 deletions

102
src/time.zig Normal file
View File

@@ -0,0 +1,102 @@
const std = @import("std");
const expect = std.testing.expect;
const expectEqualStrings = std.testing.expectEqualStrings;
const expectEqual = std.testing.expectEqual;
const Allocator = std.mem.Allocator;
pub const TimeError = error{ParsingError};
pub const Time = struct {
/// expecting a date in the format yyyy-MM-dd'T'HH:mm:ss
/// returning a unix timestamp
/// does not handle leap seconds
/// only handles UTC
pub fn parseIso8601(data: []const u8) !i64 {
const format = "nnnn-nn-nnTnn:nn:nn";
// 0123456789012345678
// validate the format
if (data.len != 19) {
return TimeError.ParsingError;
}
for (format, 0..) |formatChar, index| {
if (index >= data.len) {
return TimeError.ParsingError;
}
const c = data[index];
switch (formatChar) {
'n' => {
if (!isDigit(c)) return TimeError.ParsingError;
},
else => {
if (formatChar != c) return TimeError.ParsingError;
},
}
}
const year = try std.fmt.parseInt(i64, data[0..4], 10);
const month = try std.fmt.parseInt(i64, data[5..7], 10);
const day = try std.fmt.parseInt(i64, data[8..10], 10);
const hour = try std.fmt.parseInt(i64, data[11..13], 10);
const minute = try std.fmt.parseInt(i64, data[14..16], 10);
const second = try std.fmt.parseInt(i64, data[17..19], 10);
const unixTime: i64 = (year - 1970) * 365 * 24 * 3600 //
+ leapDays(year, month) * 24 * 3600 //
+ dayInYear(month, day) * 24 * 3600 //
+ hour * 3600 //
+ minute * 60 //
+ second;
return unixTime;
}
fn isDigit(byte: u8) bool {
return byte >= '0' and byte <= '9';
}
fn dayInYear(month: i64, day: i64) i64 {
const daysPerMonth = [_]u8{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
var result: i64 = 0;
var i: u8 = 0;
while (i < (month - 1)) : (i += 1) {
result += daysPerMonth[i];
}
result += day - 1;
return result;
}
fn leapDays(year: i64, month: i64) i64 {
var i: u64 = 1972;
var result: i64 = 0;
while (i < year) : (i += 1) {
if (@mod(i, 4) == 0 and (i % 100 != 0 or @mod(i, 400) == 0)) {
result += 1;
}
}
if (month > 2 and @mod(year, 4) == 0 and (@mod(year, 100) != 0 or @mod(year, 400) == 0)) {
result += 1;
}
return result;
}
};
test "parsing error 'x025-01-01T00:00:00'" {
try std.testing.expectError(TimeError.ParsingError, Time.parseIso8601("x025-01-01T00:00:00"));
}
test "parsing error '2025-01-01'" {
try std.testing.expectError(TimeError.ParsingError, Time.parseIso8601("2025-01-01T"));
}
//test "parsing validation successfull" {
// const y = try Time.parseIso8601("2025-12-13T01:02:03");
// try expectEqual(12, y);
//}
test "parse 2025-02-18T18:37:45, expecting 1739903865" {
const unixTime = try Time.parseIso8601("2025-02-18T18:37:45");
try expectEqual(1739903865, unixTime);
}