mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
AK/Time: Improve the accuracy of seconds_since_epoch_to_year()
The seconds_since_epoch_to_year() used an innacurate aproximation, causing problems near year boundaries. The new version relies upon the days_since_epoch_to_date() which uses a much better algorithmn.
This commit is contained in:
committed by
Lucas Chollet
parent
87d6582ed3
commit
056f1d9578
31
AK/Time.h
31
AK/Time.h
@@ -125,25 +125,6 @@ constexpr i64 days_since_epoch(int year, int month, int day)
|
||||
return years_to_days_since_epoch(year) + day_of_year(year, month, day);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
@@ -175,6 +156,14 @@ constexpr Tuple<T, u8, u8> days_since_epoch_to_date(T days)
|
||||
return { year, month, day };
|
||||
}
|
||||
|
||||
constexpr i64 seconds_since_epoch_to_year(i64 seconds)
|
||||
{
|
||||
constexpr auto seconds_per_day = 60 * 60 * 24;
|
||||
i64 day_offset_to_epoch = seconds >= 0 ? seconds / seconds_per_day : floor_div(seconds, seconds_per_day);
|
||||
auto [year, month, day] = days_since_epoch_to_date(day_offset_to_epoch);
|
||||
return year;
|
||||
}
|
||||
|
||||
// Represents a duration in a "safe" way.
|
||||
// Minimum: -(2**63) seconds, 0 nanoseconds
|
||||
// Maximum: 2**63-1 seconds, 999'999'999 nanoseconds
|
||||
@@ -707,13 +696,11 @@ using AK::day_of_year;
|
||||
using AK::days_in_month;
|
||||
using AK::days_in_year;
|
||||
using AK::days_since_epoch;
|
||||
using AK::days_since_epoch_to_date;
|
||||
using AK::Duration;
|
||||
using AK::is_leap_year;
|
||||
using AK::MonotonicTime;
|
||||
# ifndef KERNEL
|
||||
using AK::seconds_since_epoch_to_year;
|
||||
# endif
|
||||
using AK::days_since_epoch_to_date;
|
||||
using AK::timespec_add;
|
||||
using AK::timespec_add_timeval;
|
||||
using AK::timespec_sub;
|
||||
|
||||
Reference in New Issue
Block a user