commit 436ccb7ea99abd63cdab0d442c82e741d0e27bab Author: 諏訪子 Date: Sun Jul 30 12:06:30 2023 +0900 最初コミット diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c26d4af --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +zig-out +zig-cache diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..54a1c2d --- /dev/null +++ b/build.zig @@ -0,0 +1,27 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + + const optimize = b.standardOptimizeOption(.{}); + + const lib = b.addStaticLibrary(.{ + .name = "toki", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + b.installArtifact(lib); + + const main_tests = b.addTest(.{ + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + const run_main_tests = b.addRunArtifact(main_tests); + + const test_step = b.step("test", "Run library tests"); + test_step.dependOn(&run_main_tests.step); +} diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..c5839ac --- /dev/null +++ b/src/main.zig @@ -0,0 +1,137 @@ +const std = @import("std"); +const testing = std.testing; + +const DateTime = struct { + year: u64, + month: u64, + day: u64, + hour: u64, + minute: u64, + second: u64, +}; + +fn getDaysInMonth(year: u64) [12]u64 { + var daysInMonth = [_]u64{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + if (isLeapYear(year)) { + daysInMonth[1] += 1; + } + + return daysInMonth; +} + +fn calculateYearAndDayOfYear(days: u64) struct { year: u64, dayOfYear: u64 } { + var year: u64 = 1970; + var d = days; + while (true) { + var daysInThisYear: u64 = if (isLeapYear(year)) 366 else 365; + if (d < daysInThisYear) break; + d -= daysInThisYear; + year += 1; + } + + return .{ .year = year, .dayOfYear = d }; +} + +fn isLeapYear(year: u64) bool { + return (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0)); +} + +fn declareDateVars(seconds: u64) DateTime { + var dt = DateTime{ + .second = @mod(seconds, 60), + .minute = (@as(u64, seconds) / 60) % 60, + .hour = (seconds / 60 / 60) % 24, + .day = 0, + .month = 0, + .year = 0, + }; + + var days = seconds / 60 / 60 / 24; + + var yearAndDayOfYear = calculateYearAndDayOfYear(days); + var year: u64 = yearAndDayOfYear.year; + var dayOfYear: u64 = yearAndDayOfYear.dayOfYear; + + var month: u64 = 0; + var daysInMonth = getDaysInMonth(year); + + while (dayOfYear >= daysInMonth[month]) { + dayOfYear -= daysInMonth[month]; + month += 1; + } + + dt.month = month + 1; + dt.day = dayOfYear + 1; + dt.year = year; + return dt; +} + +pub fn unixToDateTime(timestamp: u64) DateTime { + const seconds: u64 = timestamp; + return declareDateVars(seconds); +} + +pub fn dateTimeToUnix(dateTime: DateTime) u64 { + var totalSeconds: u64 = 0; + totalSeconds += dateTime.second; + totalSeconds += dateTime.minute * 60; + totalSeconds += dateTime.hour * 60 * 60; + totalSeconds += (dateTime.day - 1) * 24 * 60 * 60; + + var daysInMonth = getDaysInMonth(dateTime.year); + var i: u64 = 0; + while (i < dateTime.month - 1) { + totalSeconds += daysInMonth[i] * 24 * 60 * 60; + i += 1; + } + + var j: u64 = 1970; + while (j < dateTime.year) { + if (isLeapYear(j)) totalSeconds += 366 * 24 * 60 * 60 else totalSeconds += 365 * 24 * 60 * 60; + j += 1; + } + + return totalSeconds; +} + +pub fn nanoToSecond(nano: u64) u64 { + var sec: u64 = @divTrunc(nano, 1_000_000_000); + return sec; +} + +test "test nanoToSecond" { + try testing.expect(nanoToSecond(1690514984429000696) == 1690514984); +} + +test "test unixToDateTime" { + var timestamp: u64 = 1633639452; + var result = unixToDateTime(timestamp); + + if (result.year != 2021) std.debug.panic("エラー:unixToDateTime.year = {}\n", .{result.year}); + try testing.expect(result.year == 2021); + if (result.month != 10) std.debug.panic("エラー:unixToDateTime.month = {}\n", .{result.month}); + try testing.expect(result.month == 10); + if (result.day != 7) std.debug.panic("エラー:unixToDateTime.day = {}\n", .{result.day}); + try testing.expect(result.day == 7); + if (result.hour != 20) std.debug.panic("エラー:unixToDateTime.hour = {}\n", .{result.hour}); + try testing.expect(result.hour == 20); + if (result.minute != 44) std.debug.panic("エラー:unixToDateTime.minute = {}\n", .{result.minute}); + try testing.expect(result.minute == 44); + if (result.second != 12) std.debug.panic("エラー:unixToDateTime.second = {}\n", .{result.second}); + try testing.expect(result.second == 12); +} + +test "test dateTimeToUnix" { + var timestamp: DateTime = .{ + .year = 2021, + .month = 10, + .day = 7, + .hour = 20, + .minute = 44, + .second = 12, + }; + var result = dateTimeToUnix(timestamp); + if (result != 1633639452) std.debug.panic("エラー:dateTimeToUnix= {}\n", .{result}); + try testing.expect(result == 1633639452); +}