Initial commit
This commit is contained in:
commit
2029bf3778
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
zig-out/
|
||||
zig-cache/
|
||||
tags
|
||||
tags.temp
|
||||
tags.lock
|
17
build.zig
Normal file
17
build.zig
Normal file
@ -0,0 +1,17 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
// Standard release options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
const lib = b.addStaticLibrary("zigDateTime", "src/main.zig");
|
||||
lib.setBuildMode(mode);
|
||||
lib.install();
|
||||
|
||||
const main_tests = b.addTest("src/main.zig");
|
||||
main_tests.setBuildMode(mode);
|
||||
|
||||
const test_step = b.step("test", "Run library tests");
|
||||
test_step.dependOn(&main_tests.step);
|
||||
}
|
223
src/main.zig
Normal file
223
src/main.zig
Normal file
@ -0,0 +1,223 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
|
||||
pub const SECONDS_PER_MINUTE = 60;
|
||||
pub const SECONDS_PER_HOUR = 60 * 60;
|
||||
pub const SECONDS_PER_DAY = SECONDS_PER_HOUR * 24;
|
||||
|
||||
pub const YearTag = enum(u1) {
|
||||
normal,
|
||||
leap,
|
||||
|
||||
fn new(year: u31) YearTag {
|
||||
return if (year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)) .leap else .normal;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Year = union(YearTag) {
|
||||
normal: u31,
|
||||
leap: u31,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn new(year: u31) Self {
|
||||
return switch (YearTag.new(year)) {
|
||||
.normal => Self{ .normal = year },
|
||||
.leap => Self{ .leap = year },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn days(self: Self) u16 {
|
||||
return switch (self) {
|
||||
.normal => 365,
|
||||
.leap => 366,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn seconds(self: Self) i64 {
|
||||
return self.days * SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
pub fn get(self: Self) u31 {
|
||||
return switch (self) {
|
||||
.normal => |year| year,
|
||||
.leap => |year| year,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: Self) Self {
|
||||
return Self.new(self.get() + 1);
|
||||
}
|
||||
|
||||
pub fn previous(self: Self) Self {
|
||||
return Self.new(self.get() - 1);
|
||||
}
|
||||
};
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
pub const Month = enum(u4) {
|
||||
january = 1,
|
||||
february = 2,
|
||||
march = 3,
|
||||
april = 4,
|
||||
may = 5,
|
||||
june = 6,
|
||||
july = 7,
|
||||
august = 8,
|
||||
september = 9,
|
||||
october = 10,
|
||||
november = 11,
|
||||
december = 12,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn days(self: Self, year: Year) u5 {
|
||||
return switch (@enumToInt(self)) {
|
||||
1, 3, 5, 7, 8, 10, 12 => 31,
|
||||
2 => switch (year) {
|
||||
.normal => 28,
|
||||
.leap => 29,
|
||||
},
|
||||
else => 30,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn seconds(self: Self) u32 {
|
||||
return self.days() * SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
pub fn next(self: Self) ?Self {
|
||||
const num = @enumToInt(self);
|
||||
return if (num < 12) @intToEnum(Self, num + 1) else null;
|
||||
}
|
||||
|
||||
pub fn previous(self: Self) ?Self {
|
||||
const num = @enumToInt(self);
|
||||
return if (num > 1) @intToEnum(Self, num - 1) else null;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pub const TimeZoneTag = enum(u1) {
|
||||
utc,
|
||||
offset,
|
||||
};
|
||||
|
||||
pub const TimeZone = union(TimeZoneTag) {
|
||||
utc: void,
|
||||
offset: i8,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn new(offset: ?i8) ?Self {
|
||||
return if (offset) |ofs| blk: {
|
||||
if (ofs < -12 or ofs > 12) {
|
||||
break :blk null;
|
||||
} else if (ofs == 0) {
|
||||
break :blk .utc;
|
||||
} else {
|
||||
break :blk Self{ .offset = ofs };
|
||||
}
|
||||
} else .utc;
|
||||
}
|
||||
};
|
||||
|
||||
test "new timezone" {
|
||||
const tz = TimeZone.new(-5).?;
|
||||
try testing.expectEqual(@as(TimeZoneTag, tz), .offset);
|
||||
switch (tz) {
|
||||
.offset => |ofs| try testing.expectEqual(ofs, -5),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
test "new timezone utc" {
|
||||
const tz0 = TimeZone.new(null).?;
|
||||
const tz1 = TimeZone.new(0).?;
|
||||
try testing.expectEqual(@as(TimeZoneTag, tz0), .utc);
|
||||
try testing.expectEqual(@as(TimeZoneTag, tz1), .utc);
|
||||
}
|
||||
|
||||
pub const DateTime = struct {
|
||||
year: Year,
|
||||
month: Month,
|
||||
day: u8,
|
||||
hour: ?u5,
|
||||
minute: ?u6,
|
||||
second: ?u6,
|
||||
nanos: ?u32,
|
||||
tz: TimeZone,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn getYear(self: Self) u32 {
|
||||
return self.year.get();
|
||||
}
|
||||
|
||||
pub fn getOffset(self: Self) ?i8 {
|
||||
return switch (self.tz) {
|
||||
.utc => null,
|
||||
.offset => |ofs| ofs,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
test "get year" {
|
||||
const dt = DateTime{
|
||||
.year = Year.new(2023),
|
||||
.month = .june,
|
||||
.day = 12,
|
||||
.hour = 1,
|
||||
.minute = 5,
|
||||
.second = 14,
|
||||
.nanos = null,
|
||||
.tz = TimeZone.new(-5).?,
|
||||
};
|
||||
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,
|
||||
.nanos = null,
|
||||
.tz = TimeZone.new(-5).?,
|
||||
};
|
||||
try testing.expectEqual(dt.getOffset().?, -5);
|
||||
}
|
Loading…
Reference in New Issue
Block a user