/src/unit/src/nxt_gmtime.c
Line | Count | Source |
1 | | |
2 | | /* |
3 | | * Copyright (C) Igor Sysoev |
4 | | * Copyright (C) NGINX, Inc. |
5 | | */ |
6 | | |
7 | | #include <nxt_main.h> |
8 | | |
9 | | |
10 | | /* The function is valid for positive nxt_time_t only. */ |
11 | | |
12 | | void |
13 | | nxt_gmtime(nxt_time_t s, struct tm *tm) |
14 | 0 | { |
15 | 0 | nxt_int_t yday; |
16 | 0 | nxt_uint_t daytime, mday, mon, year, days, leap; |
17 | |
|
18 | 0 | days = (nxt_uint_t) (s / 86400); |
19 | 0 | daytime = (nxt_uint_t) (s % 86400); |
20 | | |
21 | | /* January 1, 1970 was Thursday. */ |
22 | 0 | tm->tm_wday = (4 + days) % 7; |
23 | | |
24 | | /* The algorithm based on Gauss' formula. */ |
25 | | |
26 | | /* Days since March 1, 1 BCE. */ |
27 | 0 | days = days - (31 + 28) + 719527; |
28 | | |
29 | | /* |
30 | | * The "days" should be adjusted by 1 only, however some March 1st's |
31 | | * go to previous year, so "days" are adjusted by 2. This also shifts |
32 | | * the last February days to the next year, but this is catched by |
33 | | * negative "yday". |
34 | | */ |
35 | 0 | year = (days + 2) * 400 / (365 * 400 + 100 - 4 + 1); |
36 | |
|
37 | 0 | yday = days - (365 * year + year / 4 - year / 100 + year / 400); |
38 | |
|
39 | 0 | leap = (year % 4 == 0) && (year % 100 || (year % 400 == 0)); |
40 | |
|
41 | 0 | if (yday < 0) { |
42 | 0 | yday = 365 + leap + yday; |
43 | 0 | year--; |
44 | 0 | } |
45 | | |
46 | | /* |
47 | | * An empirical formula that maps "yday" to month. |
48 | | * There are at least 10 variants, some of them are: |
49 | | * mon = (yday + 31) * 15 / 459 |
50 | | * mon = (yday + 31) * 17 / 520 |
51 | | * mon = (yday + 31) * 20 / 612 |
52 | | */ |
53 | |
|
54 | 0 | mon = (yday + 31) * 10 / 306; |
55 | | |
56 | | /* The Gauss' formula that evaluates days before month. */ |
57 | |
|
58 | 0 | mday = yday - (367 * mon / 12 - 30) + 1; |
59 | |
|
60 | 0 | if (yday >= 306) { |
61 | 0 | year++; |
62 | 0 | mon -= 11; |
63 | 0 | yday -= 306; |
64 | |
|
65 | 0 | } else { |
66 | 0 | mon++; |
67 | 0 | yday += 31 + 28 + leap; |
68 | 0 | } |
69 | |
|
70 | 0 | tm->tm_mday = mday; |
71 | 0 | tm->tm_mon = mon; |
72 | 0 | tm->tm_year = year - 1900; |
73 | 0 | tm->tm_yday = yday; |
74 | |
|
75 | 0 | tm->tm_hour = daytime / 3600; |
76 | 0 | daytime %= 3600; |
77 | 0 | tm->tm_min = daytime / 60; |
78 | 0 | tm->tm_sec = daytime % 60; |
79 | 0 | } |