Last active
April 12, 2023 22:47
-
-
Save alogic0/a6886bc40f471b71035696774161872d to your computer and use it in GitHub Desktop.
calc orthodox Easter day
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const expect = std.testing.expect; | |
const expectEqualDeep = std.testing.expectEqualDeep; | |
const stdout = std.io.getStdOut().writer(); | |
const stderr = std.io.getStdErr().writer(); | |
const cumdaytab = [_][14]i32{ | |
[_]i32{ 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, | |
[_]i32{ 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | |
}; | |
const Date = struct { | |
year: i32, | |
month: [*:0]const u8, | |
day: i32, | |
}; | |
const months = [_][*:0]const u8{ | |
"January", "February", "March", "April", | |
"May", "June", "July", "August", | |
"September", "October", "November", "December", | |
}; | |
pub fn isleap(y: i32) bool { | |
return ((@mod(y, 4) == 0) and (@mod(y, 100) != 0)) or (@mod(y, 400) == 0); | |
} | |
pub fn j2g(year: i32) i32 { | |
return if (year < 1500) | |
0 | |
else | |
10 + (@divTrunc(year, 100) - 16) - @divTrunc((@divTrunc(year, 100) - 16), 4); | |
} | |
/// gets day in a month for numbered day in a year | |
/// 2023, 106 -> .{2023, April, 16} | |
fn get_date(year: i32, day: i32) Date { | |
const cumday: [14]i32 = cumdaytab[@as(usize, @boolToInt(isleap(year)))]; | |
var i: usize = 0; | |
while (cumday[i] + 2 < day) : (i += 1) {} | |
const date = Date{ | |
.year = year, | |
.month = months[i - 2], | |
.day = day - cumday[i - 1] - 1, | |
}; | |
return date; | |
} | |
test "date of 31" { | |
try expectEqualDeep(get_date(2023, 31), Date{ .year = 2023, .month = "January", .day = 31 }); | |
} | |
pub fn paskha(year: i32) i32 { | |
var a = @mod(year, 19); | |
var b = @mod(year, 4); | |
var c = @mod(year, 7); | |
var d = @mod((19 * a + 15), 30); | |
var e = @mod((2 * b + 4 * c + 6 * d + 6), 7); | |
const cumday: [14]i32 = cumdaytab[@as(usize, @boolToInt(isleap(year)))]; | |
//return (cumday[3] + 1 + 22 + @as(i32, (d + e)) + j2g(year)); | |
return (cumday[3] + 1 + 22 + d + e + j2g(year)); | |
} | |
test "year 2023" { | |
try expect(paskha(2023) == 106); | |
} | |
pub fn main() !void { | |
var args = std.process.args(); | |
_ = args.next() orelse return error.UnknownError; //skip prog name | |
const year_str = args.next() orelse return error.UnknownError; | |
const year = std.fmt.parseInt(u24, year_str, 10) catch |err| { | |
try stderr.print("Cannot parse year: {s}\n", .{year_str}); | |
return err; | |
}; | |
if (year < 1) { | |
try stderr.print("Invalid year: {d}\n", .{year}); | |
return error.UnknownError; | |
} | |
const day = paskha(year); | |
const date = get_date(year, day); | |
try stdout.print("paskha in {d}: {s} {d} ({d} day)\n", .{ date.year, date.month, date.day, day }); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment