103 lines
2.7 KiB
Zig
103 lines
2.7 KiB
Zig
const std = @import("std");
|
|
const debug = std.debug;
|
|
const testing = std.testing;
|
|
|
|
pub const TimeZoneTag = enum(u1) {
|
|
utc,
|
|
offset,
|
|
};
|
|
|
|
pub const Sign = enum(u1) {
|
|
positive,
|
|
negative,
|
|
};
|
|
|
|
const HoursMinutes = struct {
|
|
hours: u4,
|
|
minutes: ?u6,
|
|
};
|
|
|
|
pub const Offset = union(Sign) {
|
|
positive: HoursMinutes,
|
|
negative: HoursMinutes,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn new(hours: i8, minutes: ?u6) ?Self {
|
|
if (hours > 12 or hours < -12) {
|
|
return null;
|
|
}
|
|
if (minutes) |m| {
|
|
if (m > 59) return null;
|
|
if (hours == 0 and m == 0) return null;
|
|
} else if (hours == 0) return null;
|
|
if (hours < 0) {
|
|
const h = @intCast(u4, @as(i8, hours) * -1);
|
|
return Self{ .negative = .{ .hours = h, .minutes = minutes } };
|
|
} else {
|
|
return Self{ .positive = .{ .hours = @intCast(u4, hours), .minutes = minutes } };
|
|
}
|
|
}
|
|
|
|
pub fn asSeconds(self: Self) i64 {
|
|
return switch (self) {
|
|
.positive => |ofs| blk: {
|
|
var seconds = @as(i64, ofs.hours) * 3600;
|
|
if (ofs.minutes) |m| seconds += (@as(i64, m) * 60);
|
|
break :blk seconds;
|
|
},
|
|
.negative => |ofs| blk: {
|
|
var seconds = @as(i64, ofs.hours) * 3600;
|
|
if (ofs.minutes) |m| seconds += (@as(i64, m) * 60);
|
|
break :blk seconds * -1;
|
|
},
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const TimeZone = union(TimeZoneTag) {
|
|
utc: void,
|
|
offset: Offset,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn new(hours: ?i8, minutes: ?u6) ?Self {
|
|
return if (hours) |h| blk: {
|
|
if (h == 0) {
|
|
break :blk .utc;
|
|
} else if (Offset.new(h, minutes)) |ofs| {
|
|
break :blk Self{ .offset = ofs };
|
|
} else {
|
|
break :blk null;
|
|
}
|
|
} else if (minutes) |m| Self{ .offset = Offset.new(0, m).? } else .utc;
|
|
}
|
|
|
|
pub fn format(
|
|
self: Self,
|
|
comptime fmt: []const u8,
|
|
options: std.fmt.FormatOptions,
|
|
writer: anytype,
|
|
) !void {
|
|
_ = fmt;
|
|
_ = options;
|
|
|
|
switch (self) {
|
|
.utc => try writer.writeAll("Z"),
|
|
.offset => |ofs| switch (ofs) {
|
|
.positive => |p| {
|
|
try writer.print("+{d:0>2}", .{p.hours});
|
|
if (p.minutes) |m| {
|
|
try writer.print(":{d:0>2}", .{m});
|
|
}
|
|
},
|
|
.negative => |n| {
|
|
try writer.print("-{d:0>2}", .{n.hours});
|
|
if (n.minutes) |m| {
|
|
try writer.print(":{d:0>2}", .{m});
|
|
}
|
|
},
|
|
},
|
|
}
|
|
}
|
|
};
|