Changes
7 changed files (+272/-0)
-
-
@@ -59,6 +59,11 @@ }}; pub const ReportOptions = struct { /// Current time should not affect report generation. However, as C function prints /// the current time, this option is necessary for snapshot testing. Will be removed /// once the report generation was replaced with Zig impelementation. now: ?datetime.Datetime = null, day_of_month: ?u5 = null, month: ?u4 = null, year_since_2000: ?c_int = null,
-
@@ -147,6 +152,21 @@ return ParseArgsError.InvalidYearSince2000;} self.year_since_2000 = y; return; } if (std.mem.eql(u8, "--now", arg)) { const next = args.next() orelse { std.log.err("{s} option requires a value", .{arg}); return ParseArgsError.MissingValue; }; const now = datetime.Datetime.fromString(next) catch |err| { std.log.err("\"{s}\" is not a valid datetime string: {s}", .{ next, @errorName(err) }); return ParseArgsError.InvalidDatetimeFormat; }; self.now = now; return; }
-
@@ -589,6 +609,35 @@ now -= tm.tm_gmtoff;} break :now now; } break :now c.time(null); }, // This block contains totally duplicated code of the above, // because `now` option will be removed soon. .report => |opts| { if (opts.now) |now| { var tm: c.tm = .{ .tm_year = now.date.year - 1900, .tm_mon = now.date.month - 1, .tm_mday = now.date.day, .tm_hour = now.time.hour, .tm_min = now.time.minute, .tm_sec = now.time.second, }; var t = c.mktime(&tm); if (now.offset) |offset| { t -= tm.tm_gmtoff; t += @as(c_long, if (offset.positive) 1 else -1) * (@as(c_long, offset.hour) * 60 + offset.minute) * std.time.s_per_min; } else if (self.utc) { t -= tm.tm_gmtoff; } break :now t; } break :now c.time(null);
-
-
-
@@ -18,4 +18,5 @@test { _ = @import("./list.zig"); _ = @import("./poll.zig"); _ = @import("./report.zig"); }
-
-
-
@@ -0,0 +1,118 @@// Copyright (C) 2025 Shota FUJI // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. // // SPDX-License-Identifier: GPL-3.0-only const std = @import("std"); const config = @import("config"); const snapshot = @import("./snapshot.zig"); test "snapshots/report_basic.txt" { var env = std.process.EnvMap.init(std.testing.allocator); defer env.deinit(); try env.put("TZ", "Asia/Tokyo"); const result = try std.process.Child.run(.{ .allocator = std.testing.allocator, .argv = &.{ config.bin, "report", "--now", "2025-07-07", "31.132484E", "29.977435N" }, .env_map = &env, }); defer std.testing.allocator.free(result.stderr); defer std.testing.allocator.free(result.stdout); try snapshot.expectMatchSnapshot(@src(), &result); } test "snapshots/report_utc.txt" { var env = std.process.EnvMap.init(std.testing.allocator); defer env.deinit(); try env.put("TZ", "Asia/Tokyo"); const result = try std.process.Child.run(.{ .allocator = std.testing.allocator, .argv = &.{ config.bin, "report", "--utc", "--now", "2025-07-07", "31.132484E", "29.977435N" }, .env_map = &env, }); defer std.testing.allocator.free(result.stderr); defer std.testing.allocator.free(result.stdout); try snapshot.expectMatchSnapshot(@src(), &result); } test "snapshots/report_2010_02_01.txt" { var env = std.process.EnvMap.init(std.testing.allocator); defer env.deinit(); try env.put("TZ", "Asia/Tokyo"); const result = try std.process.Child.run(.{ .allocator = std.testing.allocator, .argv = &.{ config.bin, "report", "--now", "2025-07-07", "d", "1", "m", "2", "y", "10", "31.132484E", "29.977435N", }, .env_map = &env, }); defer std.testing.allocator.free(result.stderr); defer std.testing.allocator.free(result.stdout); try snapshot.expectMatchSnapshot(@src(), &result); } test "snapshots/report_christmas_island_2022_03_15.txt" { // From original USAGE.txt // > Produce a report of the different sunrises and sunsets on an arbitrary day (2022/03/15) for an arbitrary location (Christmas Island) var env = std.process.EnvMap.init(std.testing.allocator); defer env.deinit(); try env.put("TZ", "Asia/Taipei"); const result = try std.process.Child.run(.{ .allocator = std.testing.allocator, .argv = &.{ config.bin, "report", "--now", "2025-07-07", "d", "15", "m", "3", "y", "20", "10.49S", "105.55E", }, .env_map = &env, }); defer std.testing.allocator.free(result.stderr); defer std.testing.allocator.free(result.stdout); try snapshot.expectMatchSnapshot(@src(), &result); }
-
-
-
@@ -0,0 +1,26 @@Current Date and Time: 07-Jul-2025 00:00 Asia Target Information ... Location: 29.977435N, 31.132484E Date: 01-Feb-2010 Timezone: Asia Sun directly north/south: 10:08 Twilight angle: -0.83 degrees (daylight) Day with twilight: 04:45 to 15:32 It is: Night General Information (no offset) ... Times ... Daylight: 04:45 to 15:32 with Civil twilight: 04:21 to 15:56 with Nautical twilight: 03:52 to 16:24 with Astronomical twilight: 03:24 to 16:53 Duration ... Day length: 10:47 hours with civil twilight: 11:34 hours with nautical twilight: 12:32 hours with astronomical twilight: 13:28 hours
-
-
-
@@ -0,0 +1,26 @@Current Date and Time: 07-Jul-2025 00:00 Asia Target Information ... Location: 29.977435N, 31.132484E Date: 07-Jul-2025 Timezone: Asia Sun directly north/south: 10:00 Twilight angle: -0.83 degrees (daylight) Day with twilight: 02:58 to 17:01 It is: Night General Information (no offset) ... Times ... Daylight: 02:58 to 17:01 with Civil twilight: 02:32 to 17:27 with Nautical twilight: 01:59 to 18:00 with Astronomical twilight: 01:24 to 18:35 Duration ... Day length: 14:02 hours with civil twilight: 14:54 hours with nautical twilight: 16:00 hours with astronomical twilight: 17:11 hours
-
-
-
@@ -0,0 +1,26 @@Current Date and Time: 07-Jul-2025 00:00 Asia Target Information ... Location: -10.490000N, 105.550000E Date: 15-Mar-2020 Timezone: Asia Sun directly north/south: 05:06 Twilight angle: -0.83 degrees (daylight) Day with twilight: 23:01 to 11:13 It is: Day (or twilight) General Information (no offset) ... Times ... Daylight: 23:01 to 11:13 with Civil twilight: 22:41 to 11:33 with Nautical twilight: 22:17 to 11:57 with Astronomical twilight: 21:52 to 12:22 Duration ... Day length: 12:12 hours with civil twilight: 12:52 hours with nautical twilight: 13:41 hours with astronomical twilight: 14:30 hours
-
-
-
@@ -0,0 +1,26 @@Current Date and Time: 07-Jul-2025 00:00 GMT Target Information ... Location: 29.977435N, 31.132484E Date: 07-Jul-2025 Timezone: GMT Sun directly north/south: 10:00 Twilight angle: -0.83 degrees (daylight) Day with twilight: 02:58 to 17:01 It is: Night General Information (no offset) ... Times ... Daylight: 02:58 to 17:01 with Civil twilight: 02:32 to 17:27 with Nautical twilight: 01:59 to 18:00 with Astronomical twilight: 01:24 to 18:35 Duration ... Day length: 14:02 hours with civil twilight: 14:54 hours with nautical twilight: 16:00 hours with astronomical twilight: 17:11 hours
-