aboutsummaryrefslogtreecommitdiff
path: root/system.old/libraries/datetime/time.zig
diff options
context:
space:
mode:
Diffstat (limited to 'system.old/libraries/datetime/time.zig')
-rw-r--r--system.old/libraries/datetime/time.zig77
1 files changed, 77 insertions, 0 deletions
diff --git a/system.old/libraries/datetime/time.zig b/system.old/libraries/datetime/time.zig
new file mode 100644
index 0000000..9634ace
--- /dev/null
+++ b/system.old/libraries/datetime/time.zig
@@ -0,0 +1,77 @@
+//! Time operations
+
+const sys = @import("sys");
+const types = @import("types.zig");
+
+const ERROR_RESULT: u64 = @bitCast(@as(i64, -1));
+
+const SECONDS_PER_DAY: u64 = 86400;
+const SECONDS_PER_HOUR: u64 = 3600;
+const SECONDS_PER_MINUTE: u64 = 60;
+const DAYS_PER_4_YEARS: u64 = 1461;
+
+const DAYS_NORMAL = [_]u64{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+const DAYS_LEAP = [_]u64{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+pub fn now() ?u64 {
+ const result = sys.syscall(.gettime, .{});
+
+ if (result == ERROR_RESULT) {
+ return null;
+ }
+
+ return result;
+}
+
+pub fn parts(timestamp: u64) types.DateTime {
+ const days_since_epoch = timestamp / SECONDS_PER_DAY;
+ const seconds_today = timestamp % SECONDS_PER_DAY;
+ const hours = seconds_today / SECONDS_PER_HOUR;
+ const minutes = (seconds_today % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
+ const seconds = seconds_today % SECONDS_PER_MINUTE;
+
+ var year: u64 = 1970;
+ var remaining_days = days_since_epoch;
+
+ const four_year_cycles = remaining_days / DAYS_PER_4_YEARS;
+ year += four_year_cycles * 4;
+ remaining_days = remaining_days % DAYS_PER_4_YEARS;
+
+ while (remaining_days >= 365) {
+ const is_leap = isLeapYear(year);
+ const days_this_year: u64 = if (is_leap) 366 else 365;
+ if (remaining_days >= days_this_year) {
+ remaining_days -= days_this_year;
+ year += 1;
+ } else {
+ break;
+ }
+ }
+
+ const is_leap = isLeapYear(year);
+ const days_in_months = if (is_leap) DAYS_LEAP else DAYS_NORMAL;
+
+ var month: u8 = 1;
+ var day: u64 = remaining_days + 1;
+
+ for (days_in_months, 0..) |days, m| {
+ if (day <= days) {
+ month = @intCast(m + 1);
+ break;
+ }
+ day -= days;
+ }
+
+ return types.DateTime{
+ .year = year,
+ .month = month,
+ .day = @intCast(day),
+ .hour = @intCast(hours),
+ .minute = @intCast(minutes),
+ .second = @intCast(seconds),
+ };
+}
+
+fn isLeapYear(year: u64) bool {
+ return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0);
+}