OSSP CVS Repository

ossp - Difference in ossp-pkg/tai/tai_cal.c versions 1.2 and 1.3
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/tai/tai_cal.c 1.2 -> 1.3

--- tai_cal.c    2003/03/23 18:00:29     1.2
+++ tai_cal.c    2005/01/24 11:04:07     1.3
@@ -30,60 +30,7 @@
 
 #include "tai.h"
 #include "tai_p.h"
-
-#if 0
-struct leap {
-    tai_ui64_t leapsec;
-} tai_tab_leapsec[] = {
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1972 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1972 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1973 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1974 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1975 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1976 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1977 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1978 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1979 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1981 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1982 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1983 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1985 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1987 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1989 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1990 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1992 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1993 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1994 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1995 Dec 31 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1997 Jun 30 23:59:60 + */
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }  /* 1998 Dec 31 23:59:60 + */
-};
-#endif
-
-#define TAI_CAL_SUNDAY       0
-#define TAI_CAL_MONDAY       1
-#define TAI_CAL_TUESDAY      2
-#define TAI_CAL_WEDNESDAY    3
-#define TAI_CAL_THURSDAY     4
-#define TAI_CAL_FRIDAY       5
-#define TAI_CAL_SATURDAY     6
-
-#define TAI_CAL_JANUARY      0
-#define TAI_CAL_FEBRUARY     1
-#define TAI_CAL_MARCH        2
-#define TAI_CAL_APRIL        3
-#define TAI_CAL_MAY          4
-#define TAI_CAL_JUNE         5
-#define TAI_CAL_JULY         6
-#define TAI_CAL_AUGUST       7
-#define TAI_CAL_SEPTEMBER    8
-#define TAI_CAL_OCTOBER      9
-#define TAI_CAL_NOVEMBER     10
-#define TAI_CAL_DECEMBER     11
-
-#define TAI_EPOCH "9223372036854775808" /* 2^62 / 2 (=2^63) meaning 1972-01-01 00:00:00 UTC was 1972-01-01 00:00:10 TAI */
-#define TAI_EPOCH_YEAR      1970
-#define TAI_EPOCH_WDAY      TAI_CAL_THURSDAY
+#include "tai_cal.h"
 
 /* the Gregorian calendar */
 #define TAI_CAL_SECS_PER_MIN      60
@@ -96,59 +43,181 @@
 #define TAI_CAL_SECS_PER_DAY      (TAI_CAL_SECS_PER_HOUR * TAI_CAL_HOURS_PER_DAY)
 #define TAI_CAL_MONS_PER_YEAR     12
 
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+/* 2^64/2 (=2^63) meaning Thu 1972-01-01 00:00:00 UTC was Thu 1972-01-01 00:00:10 TAI */
+#define TAI_EPOCH_BASE            "8000000000000000"
+#define TAI_EPOCH_YEAR            1970
+#define TAI_EPOCH_WDAY            TAI_CAL_THURSDAY
+
+/* A year that has 366 days instead of 365 days, is a leap year,
+   February has 29 days instead of 28 in a leap year. Leap years fall on
+   any year that either can be evenly divisible by 4 and is not evenly
+   divisible by 100, or is evenly divisible by 400. For example, the
+   year 2000 is a leap year, but 1900 is not. */
+#define tai_cal_is_leap_year(y) \
+    (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define tai_leapdays_between_years(y1,y2) \
+    (  ((y1) / 4 - (y1) / 100 + (y1) / 400) \
+     - ((y2) / 4 - (y2) / 100 + (y2) / 400))
+
+static const int tai_cal_mon_len[2][TAI_CAL_MONS_PER_YEAR] = {
+    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+    { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
 
-tai_rc_t tai_tai2cal(tai_t *tai, int offset)
+static const int tai_cal_year_len[2] = {
+    TAI_CAL_DAYS_PER_NYEAR,
+    TAI_CAL_DAYS_PER_LYEAR
+};
+
+struct tai_leapsec_st {
+    ui64_t trans;
+    int corr;
+} tai_tab_leapsec[] = {
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1972 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1972 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1973 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1974 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1975 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1976 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1977 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1978 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1979 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1981 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1982 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1983 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1985 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1987 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1989 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1990 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1992 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1993 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1994 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1995 Dec 31 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }, /* 1997 Jun 30 23:59:60 */
+    { ui64_cons(00,00,00,00,00,00,00,00), 1 }  /* 1998 Dec 31 23:59:60 */
+};
+
+tai_rc_t tai_tai2cal(const tai_t *tai, tai_cal_t *cal, long offset, int isdst)
 {
-    tai_ui64_t secs;
-    tai_ui64_t days;
-    tai_ui64_t rem;
-    tai_ui64_t tmp;
-    tai_ui64_t tmp2;
-    int lshit;
+    ui64_t secs;
+    ui64_t days;
+    ui64_t rem;
+    ui64_t tmp;
+    ui64_t tmp2;
+    int ls_corr;
+    int ls_hit;
+    int cmp;
+    int yleap;
+    int year;
+    int dyear;
+    int ddays;
+    int i;
 
+    /* calculate (rounded) number of total seconds */
     secs = tai->sec;
+    if (ui64_cmp(tai->asec, tai_half_sec_in_asec) > 0)
+        ui64_addn(secs, 1, NULL);
 
-    /* perform leap second correction */
-    lshit = 0; /* FIXME */
+    /* calculate involved leap seconds */
+    ls_corr = 0;
+    ls_hit  = 0;
+    for (i = 0; i < (sizeof(tai_tab_leapsec)/sizeof(tai_tab_leapsec[0])); i++) {
+        cmp = ui64_cmp(secs, tai_tab_leapsec[i].trans);
+        if (cmp > 0)
+            break;
+        if (cmp == 0)
+            ls_hit = tai_tab_leapsec[i].corr;
+        ls_corr += tai_tab_leapsec[i].corr;
+    }
+    if (ls_corr > 0)
+        secs = ui64_addn(secs, ls_corr, NULL);
+    else
+        secs = ui64_subn(secs, -ls_corr, NULL);
 
     /* perform timezone offset correction */
-    secs = tai_ui64_addn(secs, offset, NULL);
+    if (offset > 0)
+        secs = ui64_addn(secs, offset, NULL);
+    else
+        secs = ui64_subn(secs, -offset, NULL);
+    cal->offs = offset;
+
+    /* perform Daylight Saving Time (DST) offset correction */
+    if (isdst)
+        secs = ui64_addn(secs, 1, NULL); /* FIXME */
+    cal->isdst = isdst;
 
     /* days = secs / TAI_CAL_SECS_PER_DAY
        rem  = secs % TAI_CAL_SECS_PER_DAY */
-    tmp  = tai_ui64_n2i(TAI_CAL_SECS_PER_DAY);
-    days = tai_ui64_div(secs, tmp, &rem);
+    tmp  = ui64_n2i(TAI_CAL_SECS_PER_DAY);
+    days = ui64_div(secs, tmp, &rem);
 
     /* hour = rem / TAI_CAL_SECS_PER_HOUR
        rem  = rem % TAI_CAL_SECS_PER_HOUR */
-    tmp  = tai_ui64_n2i(TAI_CAL_SECS_PER_HOUR);
-    tmp = tai_ui64_div(rem, tmp, &rem);
-    tai->tai_hour = (int)tai_ui64_i2n(tmp);
+    tmp = ui64_n2i(TAI_CAL_SECS_PER_HOUR);
+    tmp = ui64_div(rem, tmp, &rem);
+    cal->hour = (int)ui64_i2n(tmp);
 
     /* min = rem / TAI_CAL_SECS_PER_MIN
        rem = rem % TAI_CAL_SECS_PER_MIN */
-    tmp  = tai_ui64_n2i(TAI_CAL_SECS_PER_MIN);
-    tmp = tai_ui64_div(rem, tmp, &rem);
-    tai->tai_min = (int)tai_ui64_i2n(tmp);
+    tmp = ui64_n2i(TAI_CAL_SECS_PER_MIN);
+    tmp = ui64_div(rem, tmp, &rem);
+    cal->min = (int)ui64_i2n(tmp);
 
-    /* sec = rem + lshit */
-    tai->tai_sec = (int)tai_ui64_i2n(rem) + lshit;
+    /* sec = rem + ls_hit */
+    cal->sec = (int)ui64_i2n(rem) + ls_hit;
 
     /* wday = (TAI_EPOCH_WDAY + days) % TAI_CAL_DAYS_PER_WEEK */
     /* FIXME: TAI is not 0 on EPOCH */
-    tmp = tai_ui64_addn(days, TAI_EPOCH_WDAY, NULL);
-    tmp2 = tai_ui64_n2i(TAI_CAL_DAYS_PER_WEEK);
-    tai_ui64_div(tmp, tmp2, &tmp);
-    tai->tai_wday = (int)tai_ui64_i2n(tmp);
+    tmp  = ui64_addn(days, TAI_EPOCH_WDAY, NULL);
+    tmp2 = ui64_n2i(TAI_CAL_DAYS_PER_WEEK);
+    ui64_div(tmp, tmp2, &tmp);
+    cal->wday = (int)ui64_i2n(tmp);
+
+    /* What about the -10 offset in 1972 (epoch)? */
+
+    /* calculate year */
+    epoch = ui64_s2i(TAI_EPOCH_BASE, NULL, 16);
+    epoch = ui64_divn(epoch, TAI_CAL_SECS_PER_DAY, NULL);
+    year = TAI_EPOCH_YEAR;
+    if (ui64_cmp(days, epoch) > 0) {
+        /* date after the epoch */
+        ui64_sub(days, epoch, &days);
+        dyear = ui64_i2n(ui64_div(days, ui64_n2i(TAI_CAL_DAYS_PER_NYEAR), NULL));
+        ddays = ui64_muln(ui64_n2i(dyear), TAI_CAL_DAYS_PER_NYEAR);
+        ddays = ui64_addn(ddays, tai_leapdays_between_years(year+dyear-1, year-1));
+        days = ui64_sub(days, ddays, NULL);
+        years += dyear;
+    }
+    else {
+        /* date before the epoch */
+        ui64_sub(epoch, days, &days);
+        dyear = ui64_i2n(ui64_div(days, ui64_n2i(TAI_CAL_DAYS_PER_NYEAR), NULL));
+        ddays = ui64_muln(ui64_n2i(dyear), TAI_CAL_DAYS_PER_NYEAR);
+        ddays = ui64_addn(ddays, tai_leapdays_between_years(year+dyear-1, year-1));
+        days = ui64_sub(days, ddays, NULL);
+        years -= dyear;
+    }
+    cal->year = year;
+
+    /* calculate day of the year */
+    cal->yday = ui64_i2n(days);
+
+    /* calculate month of the year */
+    cal->mon = 0;
+    while (days >= tai_cal_mon_len[yleap][cal->mon]) {
+        days = ui64_subn(days, tai_cal_mon_len[yleap][cal->mon], NULL);
+        cal->mon++;
+    }
+
+    /* calculate day of the month */
+    cal->mday = ui64_i2n(days) + 1;
 
-    tai->tai_gmtoff = (long)offset;
-    
     return TAI_OK;
 }
 
-tai_rc_t tai_cal2tai(tai_t *tai)
+tai_rc_t tai_cal2tai(tai_t *tai, const tai_cal_t *cal, long *offset, int *isdst)
 {
+    /* FIXME: binary search with tai_tai2cal!! See mktime implementations!! */
     return TAI_OK;
 }
 

CVSTrac 2.0.1