Skip to content

Commit

Permalink
to v0.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
FObersteiner committed Jun 9, 2024
1 parent 112a6ba commit f3dcf90
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 94 deletions.
2 changes: 1 addition & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const std = @import("std");
const builtin = @import("builtin");
const log = std.log.scoped(.zdt_build);

const zdt_version = std.SemanticVersion{ .major = 0, .minor = 1, .patch = 2 };
const zdt_version = std.SemanticVersion{ .major = 0, .minor = 1, .patch = 3 };

const example_files = [_][]const u8{
"ex_demo",
Expand Down
2 changes: 1 addition & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.{
.name = "zdt",
.version = "0.1.2",
.version = "0.1.3",
.paths = .{
"zdt.zig",
"lib",
Expand Down
4 changes: 4 additions & 0 deletions docs/change.log
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 2024-06-09, v0.1.3

- cleaun-up calendar.zig

## 2024-05-30

- add autodoc workflow, gh pages
Expand Down
111 changes: 21 additions & 90 deletions lib/calendar.zig
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
//! calendric stuff
const std = @import("std");
const Datetime = @import("./Datetime.zig");
const assert = std.debug.assert;

/// Days per month, depending on if it comes from a leap year.
/// Based on Neri/Schneider's "Euclidean affine functions"
pub fn daysInMonth(m: u8, is_leap: bool) u8 {
std.debug.assert((m > 0) and (m < 13));
if (m == 2) return if (is_leap) 29 else 28;
return 30 | (m ^ (m >> 3));
}
const Datetime = @import("./Datetime.zig");

/// Number of days in a certain month of any year.
pub fn lastDayOfMonth(year: u16, month: u8) u8 {
Expand Down Expand Up @@ -153,7 +147,7 @@ pub fn unixdaysFromDate(ymd: [3]u16) i32 {
}

/// Calculate a Gregorian calendar date (year-month-day) from days since
/// the Unix epoch, 1970-01-01 00:00 Z.
/// the Unix epoch (1970-01-01).
/// The result is time zone naive, however resembles UTC since that is what
/// the Unix epoch refers to.
/// Based on Howard Hinnant 'date' algorithms, https://howardhinnant.github.io/date_algorithms.html
Expand Down Expand Up @@ -197,73 +191,28 @@ pub fn dateFromUnixdays(unix_days: i32) [3]u16 { // i23 should covert the range
return [_]u16{ y, m, d };
}

//
//
// --- from https://github.com/travisstaloch/date-zig/blob/main/src/lib.zig ---
// --- vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ---
//
/// Determine if the given year is a leap year
///
/// # Panics
///
/// Year must be between [YEAR_MIN] and [YEAR_MAX] inclusive. Bounds are checked
/// using `std.debug.assert` only, so that the checks are not present in release
/// builds, similar to integer overflow checks.
///
/// # Examples
///
/// ```
/// try expectEqual(is_leap_year(2023), false);
/// try expectEqual(is_leap_year(2024), true);
/// try expectEqual(is_leap_year(2100), false);
/// try expectEqual(is_leap_year(2400), true);
/// ```
///
/// # Algorithm
///
/// Algorithm is Neri-Schneider from C++now 2023 conference:
/// > https://github.com/boostcon/cppnow_presentations_2023/blob/main/cppnow_slides/Speeding_Date_Implementing_Fast_Calendar_Algorithms.pdf
// ----------------------------------------------------------------------------
// Like the two algorithms 'dateFromUnixdays' and 'unixdaysFromDate' above,
// the following code hasn't grown on my fields.
// It is mostly adapted from Travis Staloc,
// <https://github.com/travisstaloch/date-zig/>, which in turn is based on
// Neri & Schneiders paper on the use of Euclidian affine functions to calendar
// algorithms, <https://dx.doi.org/10.1002/spe.3172>.

// variant proposed by @Validark in a discussion on
// <https://ziggit.dev/t/benchmarking-isdigit/> - compiles to asm with one
// short branch (not a leap year, hitted ~75% of the time) and one longer
// branch.
/// Determine if 'year' is a leap year.
pub fn isLeapYear(y: u16) bool {
// Using `%` instead of `&` causes compiler to emit branches instead. This
// is faster in a tight loop due to good branch prediction, but probably
// slower in a real program so we use `&`. Also `% 25` is functionally
// equivalent to `% 100` here, but a little cheaper to compute. If branches
// were to be emitted, using `% 100` would be most likely faster due to
// better branch prediction.
return if (@mod(y, 25) != 0)
y & 3 == 0
else
y & 15 == 0;
// NOTE : this is actually slower than the standard lib implementation
return (y % 4) == 0 and (y % 25 != 0 or (y & 15) == 0);
}

/// Determine the number of days in the given month in the given year
///
/// # Panics
///
/// Year must be between [YEAR_MIN] and [YEAR_MAX]. Month must be between `1`
/// and `12`. Bounds are checked using `std.debug.assert` only, so that the checks
/// are not present in release builds, similar to integer overflow checks.
///
/// # Example
///
/// ```
/// try expectEqual(days_in_month(2023, 1), 31);
/// try expectEqual(days_in_month(2023, 2), 28);
/// try expectEqual(days_in_month(2023, 4), 30);
/// try expectEqual(days_in_month(2024, 1), 31);
/// try expectEqual(days_in_month(2024, 2), 29);
/// try expectEqual(days_in_month(2024, 4), 30);
/// ```
///
/// # Algorithm
///
/// Algorithm is Neri-Schneider from C++now 2023 conference:
/// > https://github.com/boostcon/cppnow_presentations_2023/blob/main/cppnow_slides/Speeding_Date_Implementing_Fast_Calendar_Algorithms.pdf
pub fn daysInMonth_(y: i32, m: u8) u8 {
return if (m != 2) 30 | (m ^ (m >> 3)) else if (isLeapYear(y)) 29 else 28;
/// Days per month, depending on if it comes from a leap year.
pub fn daysInMonth(m: u8, is_leap: bool) u8 {
return if (m != 2) 30 | (m ^ (m >> 3)) else if (is_leap) 29 else 28;
}
//

/// Adjustment from Unix epoch to make calculations use positive integers
///
/// Unit is eras, which is defined to be 400 years, as that is the period of the
Expand All @@ -286,15 +235,6 @@ const SECS_IN_DAY: i64 = 86400;
const SECS_OFFSET: i64 = DAY_OFFSET * SECS_IN_DAY;

/// Convert Rata Die / days since 0001-01-01 to Gregorian date
///
/// Given a day counting from Unix epoch (January 1st, 1970) returns a
/// `(year, month, day)` triple.
///
/// ## Algorithm
///
/// > Neri C, Schneider L. "*Euclidean affine functions and their application to
/// > calendar algorithms*". Softw Pract Exper. 2022;1-34. DOI:
/// > [10.1002/spe.3172](https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172).
pub fn rdToDate(rd: i32) [3]u16 {
const n0: u32 = @intCast(rd +% DAY_OFFSET);
// century
Expand All @@ -320,15 +260,6 @@ pub fn rdToDate(rd: i32) [3]u16 {
}

/// Convert Gregorian date to Rata Die / days since 0001-01-01
///
/// Given a `year, month, day` returns the days since Unix epoch
/// (January 1st, 1970). Dates before the epoch produce negative values.
///
/// ## Algorithm
///
/// > Neri C, Schneider L. "*Euclidean affine functions and their application to
/// > calendar algorithms*". Softw Pract Exper. 2022;1-34. DOI:
/// > [10.1002/spe.3172](https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172).
pub fn dateToRD(ymd: [3]u16) i32 {
const y1: u32 = @intCast(ymd[0] +% YEAR_OFFSET);
// map
Expand Down
4 changes: 2 additions & 2 deletions util/gen_tzdb.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub fn main() !void {

// update submodule
const argv_update = [_][]const u8{ "git", "submodule", "update", "--remote", "tz" };
const proc_update = try std.ChildProcess.run(.{
const proc_update = try std.process.Child.run(.{
.allocator = allocator,
.argv = &argv_update,
});
Expand Down Expand Up @@ -62,7 +62,7 @@ pub fn main() !void {

// compile tzdata
const argv_compile = [_][]const u8{ "make", target_dir_cmd, "ZFLAGS=-b fat", "POSIXRULES=", "install" };
const proc_compile = try std.ChildProcess.run(.{
const proc_compile = try std.process.Child.run(.{
.cwd = source_dir_abs,
.allocator = allocator,
.argv = &argv_compile,
Expand Down

0 comments on commit f3dcf90

Please sign in to comment.