Skip to content

Instantly share code, notes, and snippets.

@alogic0
Last active April 12, 2023 22:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alogic0/a6886bc40f471b71035696774161872d to your computer and use it in GitHub Desktop.
Save alogic0/a6886bc40f471b71035696774161872d to your computer and use it in GitHub Desktop.
calc orthodox Easter day
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