add parameter --time
You can not generate a code for a specific time. Currently only UTC is supported.
This commit is contained in:
102
src/time.zig
Normal file
102
src/time.zig
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user