71 lines
2.1 KiB
Zig
71 lines
2.1 KiB
Zig
const std = @import("std");
|
|
|
|
const c = @cImport({
|
|
@cInclude("time.h");
|
|
@cInclude("astro.h");
|
|
});
|
|
|
|
pub const Phase = struct {
|
|
phase: f64, // 0.0 to 1.0 (0=new, 0.25=first quarter, 0.5=full, 0.75=last quarter)
|
|
illuminated: f64, // 0.0 to 1.0
|
|
age_days: f64, // Age in days
|
|
distance_km: f64,
|
|
angular_diameter: f64,
|
|
|
|
pub fn emoji(self: Phase) []const u8 {
|
|
const p = self.phase;
|
|
if (p < 0.0625) return "🌑"; // New moon
|
|
if (p < 0.1875) return "🌒"; // Waxing crescent
|
|
if (p < 0.3125) return "🌓"; // First quarter
|
|
if (p < 0.4375) return "🌔"; // Waxing gibbous
|
|
if (p < 0.5625) return "🌕"; // Full moon
|
|
if (p < 0.6875) return "🌖"; // Waning gibbous
|
|
if (p < 0.8125) return "🌗"; // Last quarter
|
|
if (p < 0.9375) return "🌘"; // Waning crescent
|
|
return "🌑"; // New moon
|
|
}
|
|
|
|
pub fn day(self: Phase) u8 {
|
|
return @intFromFloat(@round(self.age_days));
|
|
}
|
|
};
|
|
|
|
pub fn getPhase(timestamp: i64) Phase {
|
|
const julian = c.unix_to_julian(@intCast(timestamp));
|
|
|
|
var illuminated: f64 = 0;
|
|
var age_days: f64 = 0;
|
|
var distance: f64 = 0;
|
|
var angular_diameter: f64 = 0;
|
|
var sun_distance: f64 = 0;
|
|
var sun_angular_diameter: f64 = 0;
|
|
|
|
const phase_angle = c.phase(
|
|
julian,
|
|
&illuminated,
|
|
&age_days,
|
|
&distance,
|
|
&angular_diameter,
|
|
&sun_distance,
|
|
&sun_angular_diameter,
|
|
);
|
|
|
|
return .{
|
|
.phase = phase_angle,
|
|
.illuminated = illuminated,
|
|
.age_days = age_days,
|
|
.distance_km = distance,
|
|
.angular_diameter = angular_diameter,
|
|
};
|
|
}
|
|
|
|
test "moon phase calculation" {
|
|
// Test a known date: 2024-01-01 00:00:00 UTC
|
|
const timestamp: i64 = 1704067200;
|
|
const moon = getPhase(timestamp);
|
|
|
|
try std.testing.expect(moon.phase >= 0.0 and moon.phase <= 1.0);
|
|
try std.testing.expect(moon.illuminated >= 0.0 and moon.illuminated <= 1.0);
|
|
try std.testing.expect(moon.age_days >= 0.0 and moon.age_days <= 29.53);
|
|
try std.testing.expect(moon.distance_km > 0);
|
|
}
|