Index: ossp-pkg/tai/tai.pod RCS File: /v/ossp/cvs/ossp-pkg/tai/tai.pod,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/tai/tai.pod,v' 2>/dev/null --- tai.pod 2002/04/18 09:10:45 1.1 +++ tai.pod 2005/01/24 11:04:07 1.2 @@ -12,6 +12,14 @@ =head1 DESCRIPTION ... +deci 10^(-1) +centi 10^(-2) +milli 10^(-3) +micro 10^(-6) +nano 10^(-9) +pico 10^(-12) +femto 10^(-15) +atto 10^(-18) (1000000000000000000) =head1 SEE ALSO Index: ossp-pkg/tai/tai_cal.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_cal.c,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/tai/tai_cal.c,v' 2>/dev/null --- 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; } Index: ossp-pkg/tai/tai_cal.h RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_cal.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/tai/tai_cal.h,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai_cal.h' 2>/dev/null --- ossp-pkg/tai/tai_cal.h +++ - 2024-05-03 10:59:48.562528200 +0200 @@ -0,0 +1,71 @@ +/* +** OSSP tai - Time Handling +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** +** This file is part of OSSP tai, a time handling library +** which can be found at http://www.ossp.org/pkg/lib/tai/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** tai_cal.h: calendar calculations (header) +*/ + +#ifndef __TAI_CAL_H__ +#define __TAI_CAL_H__ + +#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_CAL_YEAR_BASE 1900 + +typedef struct { + int sec; /* seconds after the minute [0-61] */ + int min; /* minutes after the hour [0-59] */ + int hour; /* hours since midnight [0-23] */ + int mday; /* day of the month [1-31] */ + int mon; /* months since January [0-11] */ + int year; /* years since 1900 */ + int wday; /* days since Sunday [0-6] */ + int yday; /* days since January 1 [0-365] */ + long offs; /* offset from UTC+0 in seconds */ + int isdst; /* Daylight Savings Time flag */ +} tai_cal_t; + +#endif /* __TAI_CAL_H__ */ + Index: ossp-pkg/tai/tai_data.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_data.c,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/tai/tai_data.c,v' 2>/dev/null --- tai_data.c 2002/08/14 14:28:27 1.2 +++ tai_data.c 2005/01/24 11:04:07 1.3 @@ -36,6 +36,12 @@ #include "tai_p.h" +/* ui64 representation of a full second in atto seconds, i.e. 10^(-18) atto-seconds */ +ui64_t tai_full_sec_in_asec = ui64_cons(0D,E0,B6,B3,A7,64,00,00); + +/* ui64 representation of a half second in atto seconds, i.e. (10^(-18)/2) atto-seconds */ +ui64_t tai_half_sec_in_asec = ui64_cons(06,F0,5B,59,D3,B2,00,00); + #define LCTIME_SIZE (sizeof(tai_locale_t) / sizeof(char *)) const tai_locale_t tai_locale = { Index: ossp-pkg/tai/tai_lib.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_lib.c,v rcsdiff -q -kk '-r1.8' '-r1.9' -u '/v/ossp/cvs/ossp-pkg/tai/tai_lib.c,v' 2>/dev/null --- tai_lib.c 2003/03/23 18:00:29 1.8 +++ tai_lib.c 2005/01/24 11:04:07 1.9 @@ -158,8 +158,8 @@ else if (type == TAI_TYPE_UNIX) { /* import from time(3) FIXME */ time_t t = time(NULL); - tai->sec = tai_ui64_n2i((unsigned long)t); - tai->asec = tai_ui64_n2i((unsigned long)0); + tai->sec = ui64_n2i((unsigned long)t); + tai->asec = ui64_n2i((unsigned long)0); tai_tai2cal(tai, 7200); } else Index: ossp-pkg/tai/tai_p.h RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_p.h,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/tai/tai_p.h,v' 2>/dev/null --- tai_p.h 2002/08/14 14:28:27 1.4 +++ tai_p.h 2005/01/24 11:04:07 1.5 @@ -34,6 +34,7 @@ #include "config.h" #include "tai.h" #include "tai_ui64.h" +#include "tai_cal.h" struct tai_st { tai_ui64_t sec; /* seconds (integral part) */ @@ -73,12 +74,13 @@ extern const tai_locale_t tai_locale; -#define TM_YEAR_BASE 1900 - size_t tai_format_int(char *const s, const size_t maxsize, const char *const format, const struct tm *const t); char *tai_parse_int (const char *buf, const char *fmt, struct tm *tm); -tai_rc_t tai_tai2cal(tai_t *tai, int offset); -tai_rc_t tai_cal2tai(tai_t *tai); +tai_rc_t tai_tai2cal(const tai_t *tai, tai_cal_t *cal, long offset, int isdst); +tai_rc_t tai_cal2tai( tai_t *tai, const tai_cal_t *cal, long *offset, int *isdst); + +extern ui64_t tai_full_sec_in_asec; +extern ui64_t tai_half_sec_in_asec; #endif /* !_TIMELOCAL_H_ */