Repository: SerenityOS/serenity
File: AK/Time.h (C/C++)

Code before:
#ifndef KERNEL
constexpr i64 seconds_since_epoch_to_year(i64 seconds)
{
    constexpr double seconds_per_year = 60.0 * 60.0 * 24.0 * 365.2425;

    // NOTE: We are not using floor() from <math.h> to avoid LibC / DynamicLoader dependency issues.
    auto round_down = [](double value) -> i64 {
        auto as_i64 = static_cast<i64>(value);

        if ((value == as_i64) || (as_i64 >= 0))
            return as_i64;
        return as_i64 - 1;
    };

    auto years_since_epoch = static_cast<double>(seconds) / seconds_per_year;
    return 1970 + round_down(years_since_epoch);
}
#endif

template<typename T>
constexpr Tuple<T, u8, u8> days_to_time(T days)
{
    // Adapted from https://howardhinnant.github.io/date_algorithms.html#civil_from_days
    static_assert(NumericLimits<T>::digits() >= 20, "This algorithm has not been ported to a 16 bit signed integer");

    constexpr u32 average_days_per_year = 365;
    constexpr u32 last_day_of_year_three = 1460;
    constexpr u32 days_in_first_hundred_era_years = 36524;
    constexpr u64 era_days = 146097;
    constexpr u32 last_day_of_era = era_days - 1;
    constexpr u32 era_month_offset = 2;
    constexpr u32 months_in_year = 12;

    // Shift the epoch from 1970-01-01 to 0000-03-01.
    days += 719468;
    T era = days / era_days;
    u32 day_of_era = days - era * era_days;
    u32 year_of_era = (day_of_era - day_of_era / last_day_of_year_three + day_of_era / days_in_first_hundred_era_years - day_of_era / last_day_of_era) / average_days_per_year;
    // The latter part of this comes from accounting for leap years (the year 400 need not be accounted for, because an era only has 400 years in total).
    u32 day_of_year_of_era = day_of_era - (average_days_per_year * year_of_era + year_of_era / 4 - year_of_era / 100);
    // Starting from March 1st, not January 1st (because that's how the algorithm works).
    u32 month_of_era = (5 * day_of_year_of_era + 2) / 153;
    u32 day = day_of_year_of_era - (153 * month_of_era + 2) / 5 + 1;
    u32 month = ((month_of_era + era_month_offset) % months_in_year) + 1;
    T year = (year_of_era + era * 400) + (month <= era_month_offset);

    return { year, month, day };
}

// Represents a duration in a "safe" way.
// Minimum: -(2**63) seconds, 0 nanoseconds

Review comment (suggestion):
365 is not the average number of days per year, use a different name (or don't have a named constant for this one as 365 looks fairly unsurprising as literal in date math code)

Code after:
#ifndef KERNEL
constexpr i64 seconds_since_epoch_to_year(i64 seconds)
{
    constexpr double seconds_per_year = 60.0 * 60.0 * 24.0 * 365.2425;

    // NOTE: We are not using floor() from <math.h> to avoid LibC / DynamicLoader dependency issues.
    auto round_down = [](double value) -> i64 {
        auto as_i64 = static_cast<i64>(value);

        if ((value == as_i64) || (as_i64 >= 0))
            return as_i64;
        return as_i64 - 1;
    };

    auto years_since_epoch = static_cast<double>(seconds) / seconds_per_year;
    return 1970 + round_down(years_since_epoch);
}
#endif

template<typename T>
constexpr Tuple<T, u8, u8> days_since_epoch_to_date(T days)
{
    // Adapted from https://howardhinnant.github.io/date_algorithms.html#civil_from_days
    static_assert(NumericLimits<T>::digits() >= 20, "This algorithm has not been ported to a 16 bit signed integer");

    // An era is a 400 year period.
    constexpr u32 last_day_of_year_three = 4 * 365;
    constexpr u32 days_in_first_hundred_era_years = 365 * 100 + 100 / 4 - 1;
    constexpr u64 era_days = 365 * 400 + 100 - 3;
    constexpr u32 last_day_of_era = era_days - 1;
    constexpr u32 era_month_offset = 2;

    // Shift the epoch from 1970-01-01 to 0000-03-01.
    VERIFY(days <= NumericLimits<T>::max() - 719468);
    days += 719468;

    T era = (days >= 0 ? days : days - last_day_of_era) / era_days;
    u32 day_of_era = days - era * era_days;
    u32 year_of_era = (day_of_era - day_of_era / last_day_of_year_three + day_of_era / days_in_first_hundred_era_years - day_of_era / last_day_of_era) / 365;
    // The latter part of this comes from accounting for leap years (the year 400 need not be accounted for, because an era only has 400 years in total).
    u32 day_of_year_of_era = day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100);
    // Starting from March 1st, not January 1st.
    u32 month_of_era = (5 * day_of_year_of_era + 2) / 153;
    u32 day = day_of_year_of_era - (153 * month_of_era + 2) / 5 + 1;
    u32 month = month_of_era < 10 ? month_of_era + 3 : month_of_era - 9;
    T year = (static_cast<T>(year_of_era) + era * 400) + (month <= era_month_offset);

    return { year, month, day };
}

// Represents a duration in a "safe" way.