最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Why is the number 2472632 used in this algorithm that calculates the current time? - Stack Overflow

programmeradmin6浏览0评论

The following C++ code is for getting the current time. I'm confused by the number 2472632 in kDaysFromUnixTime. I don't understand how it works and why the number is 2472632. It should be an epoch alignment, but the offset from Unix time should be 1721119 (from 1970.01.01 to 0000.01.01).

Could someone please tell me how to figure out the number 2472632?

Get_Now(
    const char* fmt = "%Y-%m-%d %H:%M:%S",
    int time_zone = 8)
{
        std::time_t unix_sec = std::time(nullptr);
        std::tm tm;
        static const int kHoursInDay = 24;
        static const int kMinutesInHour = 60;
        static const int kDaysFromUnixTime = 2472632;
        static const int kDaysFromYear = 153;
        static const int kDMagicUnkonwnFirst = 146097;
        static const int kMagicUnkonwnSec = 1461;
        tm.tm_sec = unix_sec %kMinutesInHour;
        int i = (unix_sec / kMinutesInHour);
        tm.tm_min = i % kMinutesInHour;
        i /= kMinutesInHour;
        tm.tm_hour = (i + time_zone) % kHoursInDay;
        tm.tm_mday = (i + time_zone) / kHoursInDay;
        int a = tm.tm_mday + kDaysFromUnixTime;
        int b = (a * 4 + 3) / kDMagicUnkonwnFirst;
        int c = (-b * kDMagicUnkonwnFirst) / 4 + a;
        int d = ((c * 4 + 3) / kMagicUnkonwnSec);
        int e = -d * kMagicUnkonwnSec;
        e = e /4 + c;
        int m = (5 * e + 2) / kDaysFromYear;
        tm.tm_mday = -(kDaysFromYear * m + 2) / 5 + e + 1;
        tm.tm_mon = (-m / 10) * 12 + m +2;
        tm.tm_year = b * 100 + d - 6700 + (m / 10);
        stringstream ss;
        ss << std::put_time(&tm, fmt);
        return ss.str();// #include <iomanip>
}

The interesting thing is, when I try to replace the number 2472632 with 1721119, it cannot output the correct time.

This is the output of the code, the first four results use the number 2472632 and the remaining results use 1721119:

2025-03-15 10:53:41;
2025-03-15 10:53:41;
2025-03-15 10:53:41;
2025-03-15 10:53:41;
-033-08-19 10:54:22;
-033-08-19 10:54:22;
-033-08-19 10:54:22;
-033-08-19 10:54:22;

The following C++ code is for getting the current time. I'm confused by the number 2472632 in kDaysFromUnixTime. I don't understand how it works and why the number is 2472632. It should be an epoch alignment, but the offset from Unix time should be 1721119 (from 1970.01.01 to 0000.01.01).

Could someone please tell me how to figure out the number 2472632?

Get_Now(
    const char* fmt = "%Y-%m-%d %H:%M:%S",
    int time_zone = 8)
{
        std::time_t unix_sec = std::time(nullptr);
        std::tm tm;
        static const int kHoursInDay = 24;
        static const int kMinutesInHour = 60;
        static const int kDaysFromUnixTime = 2472632;
        static const int kDaysFromYear = 153;
        static const int kDMagicUnkonwnFirst = 146097;
        static const int kMagicUnkonwnSec = 1461;
        tm.tm_sec = unix_sec %kMinutesInHour;
        int i = (unix_sec / kMinutesInHour);
        tm.tm_min = i % kMinutesInHour;
        i /= kMinutesInHour;
        tm.tm_hour = (i + time_zone) % kHoursInDay;
        tm.tm_mday = (i + time_zone) / kHoursInDay;
        int a = tm.tm_mday + kDaysFromUnixTime;
        int b = (a * 4 + 3) / kDMagicUnkonwnFirst;
        int c = (-b * kDMagicUnkonwnFirst) / 4 + a;
        int d = ((c * 4 + 3) / kMagicUnkonwnSec);
        int e = -d * kMagicUnkonwnSec;
        e = e /4 + c;
        int m = (5 * e + 2) / kDaysFromYear;
        tm.tm_mday = -(kDaysFromYear * m + 2) / 5 + e + 1;
        tm.tm_mon = (-m / 10) * 12 + m +2;
        tm.tm_year = b * 100 + d - 6700 + (m / 10);
        stringstream ss;
        ss << std::put_time(&tm, fmt);
        return ss.str();// #include <iomanip>
}

The interesting thing is, when I try to replace the number 2472632 with 1721119, it cannot output the correct time.

This is the output of the code, the first four results use the number 2472632 and the remaining results use 1721119:

2025-03-15 10:53:41;
2025-03-15 10:53:41;
2025-03-15 10:53:41;
2025-03-15 10:53:41;
-033-08-19 10:54:22;
-033-08-19 10:54:22;
-033-08-19 10:54:22;
-033-08-19 10:54:22;
Share Improve this question edited Mar 21 at 20:29 Remy Lebeau 601k36 gold badges507 silver badges851 bronze badges asked Mar 21 at 11:04 jimmy zhaojimmy zhao 491 silver badge1 bronze badge 6
  • 1 Unix time is the number of seconds since 00:00 on January 1, 1970. – Some programmer dude Commented Mar 21 at 11:10
  • The name kDaysFromUnixTime suggests that it's the number of days from the Unix epoch. Multiply this value with 60 and you will get the base time and date. – Some programmer dude Commented Mar 21 at 11:17
  • github/protocolbuffers/upb/blob/22182e6e/upb/json/… – Hans Passant Commented Mar 21 at 12:03
  • This is some magic number which doesn't seems to have meaning from time point of view. See 2472632 on wolframalpha. IMO this is very badly written code. This function does to much and is not testable. Name of function do not explain why this magic numbers are needed. – Marek R Commented Mar 21 at 12:14
  • Where did you come up with your own number of 1721119? I'd expect it to be close to 1970 * 365.25 = 719542.5. I suspect the variable name is misleading and it has nothing to do with the number of days between epochs, it's just a magic number like the others. – Mark Ransom Commented Mar 21 at 12:25
 |  Show 1 more comment

1 Answer 1

Reset to default 13

The number 2472632, which has the variable name kDaysFromUnixTime, is the number of days from -4800-03-01 to the Unix epoch 1970-01-01. The code you are using counts days since -4800-03-01 but changes that to a count from the Unix epoch by adjusting the count by the difference between these two epochs.

I discovered this with the following simple C++20 program:

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace chrono;
    cout << sys_days{} - days{2472632} << '\n';
}

which outputs:

-4800-03-01

Date algorithms are built around choosing an epoch and computing from it. Here is one described in detail that uses 0000-03-01. The choice of Mar 1 for the day of the epoch is because it puts the leap day as the last day of the "year", which makes things much more convenient within the algorithm.

Just fyi, my document won't explain the year -4800. This is a different algorithm than what I document. There will be similarities and differences. For example the one I document has a much larger range of validity than this one. And that range is documented. The one here is valid from about the year -2114 to 6053, which is admittedly plenty for just getting the current time. :-)

Beyond this range I detect signed integral overflows (assuming a 32 bit int). And I found it curious that this algorithm is not valid at its own epoch.

This line:

int i = (unix_sec / kMinutesInHour);

overflows when the result is prior to 1970-01-01 by more than numeric_limits<int>::min() minutes.

Using this program:

using min32 = duration<int32_t, ratio<60>>;
cout << sys_days{} + min32::min() << '\n';

outputs (assuming a 32 bit int):

-2114-12-08 21:52:00

which will be the beginning of the range of validity for this algorithm.

发布评论

评论列表(0)

  1. 暂无评论