changeset 1970:5bb2c374cab2

use more straightforward ngx_gmtime() implementation
author Igor Sysoev <igor@sysoev.ru>
date Sun, 13 Apr 2008 13:33:12 +0000
parents 41fd9a2e0755
children d7abb9e669e2
files src/core/ngx_times.c
diffstat 1 files changed, 46 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -203,14 +203,17 @@ ngx_http_cookie_time(u_char *buf, time_t
 void
 ngx_gmtime(time_t t, ngx_tm_t *tp)
 {
-    ngx_uint_t  n, sec, min, hour, mday, mon, year, wday, yday, days;
+    ngx_int_t   yday;
+    ngx_uint_t  n, sec, min, hour, mday, mon, year, wday, days, leap;
 
     /* the calculation is valid for positive time_t only */
+
     n = (ngx_uint_t) t;
 
     days = n / 86400;
 
     /* Jaunary 1, 1970 was Thursday */
+
     wday = (4 + days) % 7;
 
     n %= 86400;
@@ -219,57 +222,65 @@ ngx_gmtime(time_t t, ngx_tm_t *tp)
     min = n / 60;
     sec = n % 60;
 
-    /* the algorithm based on Gauss's formula */
+    /*
+     * the algorithm based on Gauss' formula,
+     * see src/http/ngx_http_parse_time.c
+     */
 
+    /* days since March 1, 1 BC */
     days = days - (31 + 28) + 719527;
 
-    year = days * 400 / (365 * 400 + 100 - 4 + 1);
+    /*
+     * The "days" should be adjusted to 1 only, however, some March 1st's go
+     * to previous year, so we adjust them to 2.  This causes also shift of the
+     * last Feburary days to next year, but we catch the case when "yday"
+     * becomes negative.
+     */
+
+    year = (days + 2) * 400 / (365 * 400 + 100 - 4 + 1);
+
     yday = days - (365 * year + year / 4 - year / 100 + year / 400);
 
-    mon = (yday + 31) * 12 / 367;
-    mday = yday - (mon * 367 / 12 - 31);
+    if (yday < 0) {
+        leap = (year % 4 == 0) && (year % 100 || (year % 400 == 0));
+        yday = 365 + leap + yday;
+        year--;
+    }
 
-    mon += 2;
+    /*
+     * The empirical formula that maps "yday" to month.
+     * There are at least 10 variants, some of them are:
+     *     mon = (yday + 31) * 15 / 459
+     *     mon = (yday + 31) * 17 / 520
+     *     mon = (yday + 31) * 20 / 612
+     */
+
+    mon = (yday + 31) * 10 / 306;
+
+    /* the Gauss' formula that evaluates days before the month */
+
+    mday = yday - (367 * mon / 12 - 30) + 1;
 
     if (yday >= 306) {
 
+        year++;
+        mon -= 10;
+
         /*
          * there is no "yday" in Win32 SYSTEMTIME
          *
          * yday -= 306;
          */
 
-        year++;
-        mon -= 12;
-
-        if (mday == 0) {
-            /* Jaunary 31 */
-            mon = 1;
-            mday = 31;
+    } else {
 
-        } else if (mon == 2) {
-
-            if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) {
-                if (mday > 29) {
-                    mon = 3;
-                    mday -= 29;
-                }
+        mon += 2;
 
-            } else if (mday > 28) {
-                mon = 3;
-                mday -= 28;
-            }
-        }
-/*
- *  there is no "yday" in Win32 SYSTEMTIME
- *
- *  } else {
- *      yday += 31 + 28;
- *
- *      if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) {
- *          yday++;
- *      }
- */
+        /*
+         * there is no "yday" in Win32 SYSTEMTIME
+         *
+         * yday += 31 + 28 + leap;
+         */
     }
 
     tp->ngx_tm_sec = (ngx_tm_sec_t) sec;