📄 mtime.c
字号:
#line 834 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"#include "mal_config.h"#include "mtime.h"#line 871 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"#define get_rule(r) ((r).s.weekday | ((r).s.day<<6) | ((r).s.minutes<<10) | ((r).s.month<<21))#define set_rule(r,i) { (r).s.weekday = (i)&15;\ (r).s.day = ((i)&(63<<6))>>6;\ (r).s.minutes = ((i)&(2047<<10))>>10;\ (r).s.month = ((i)&(15<<21))>>21; \ (r).s.empty = 0; /* to please valgrind */ }/* phony zero values, used to get negative numbers from unsigned sub-integers in rule */#define WEEKDAY_ZERO 8#define DAY_ZERO 32#define OFFSET_ZERO 4096#line 892 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"/* as the offset field got split in two, we need macros to get and set them */#define get_offset(z) (((int) (((z)->off1 << 7) + (z)->off2)) - OFFSET_ZERO)#define set_offset(z,i) { (z)->off1 = (((i)+4096)&8064) >> 7; (z)->off2 = ((i)+OFFSET_ZERO)&127; }tzone tzone_local;#line 1055 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"str MONTHS[13] = { NULL, "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};str DAYS[8] = { NULL, "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};str COUNT1[7] = { NULL, "first", "second", "third", "fourth", "fifth", "last" };str COUNT2[7] = { NULL, "1st", "2nd", "3rd", "4th", "5th", "last" };int NODAYS[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };date DATE_MAX, DATE_MIN; /* often used dates; computed once */#define YEAR_MAX 5867411#define YEAR_MIN -YEAR_MAX#define MONTHDAYS(m,y) (((m)!=2)?NODAYS[m]:leapyear(y)?29:28)#define YEARDAYS(y) (leapyear(y)?366:365)#define LEAPYEARS(y) (leapyears(y)+((y)>=0))#define DATE(d,m,y) ((m)>0&&(m)<=12&&(d)>0&&(y)!=0&&(y)>=YEAR_MIN&&(y)<=YEAR_MAX&&(d)<=MONTHDAYS(m,y))#define TIME(h,m,s,x) ((h)>=0&&(h)<24&&(m)>=0&&(m)<60&&(s)>=0&&(s)<60&&(x)>=0 &&(x)<1000)#define LOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c)+'a'-'A' : (c))#line 1078 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"#define tz_isnil(z) (get_offset(&(z)) == get_offset(tz_nilptr))#define ts_isnil(t) ((t).days == ts_nilptr->days && (t).msecs == ts_nilptr->msecs)static union { timestamp ts; lng nilval;} ts_nil;static union { tzone tz; lng nilval;} tz_nil;static timestamp *ts_nilptr = NULL;static tzone *tz_nilptr = NULL;static void date_prelude(void);int TYPE_date;int TYPE_daytime;int TYPE_timestamp;int TYPE_tzone;int TYPE_rule;bat *monettime_prelude(void){ ts_nil.nilval = lng_nil; tz_nil.nilval = lng_nil; ts_nilptr = &ts_nil.ts; tz_nilptr = &tz_nil.tz; TYPE_date = ATOMindex("date"); TYPE_daytime = ATOMindex("daytime"); TYPE_timestamp = ATOMindex("timestamp"); TYPE_tzone = ATOMindex("timezone"); TYPE_rule = ATOMindex("rule"); date_prelude(); return NULL;}voidmonettime_epilogue(void){}timestamp *timestamp_null(void){ return (ts_nilptr);}tzone *tzone_null(void){ return (tz_nilptr);}static int synonyms = TRUE;intmonettime_synonyms(bit *allow){ if (*allow != bit_nil) synonyms = *allow; return GDK_SUCCEED;}static INLINE intleapyear(int year){ return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);}static INLINE intleapyears(int year){ /* count the 4-fold years that passed since jan-1-0 */ int y4 = year / 4; /* count the 100-fold years */ int y100 = year / 100; /* count the 400-fold years */ int y400 = year / 400; return y4 + y400 - y100; /* may be negative */}static INLINE datetodate(int day, int month, int year){ date n = date_nil; if (DATE(day, month, year)) { if (year < 0) year++; /* HACK: hide year 0 */ for (n = (date) (day - 1); --month > 0; n += MONTHDAYS(month, year)) ; /* current year does not count as leapyear */ n += 365 * year + LEAPYEARS(year >= 0 ? year - 1 : year); } return n;}voidfromdate(int n, int *d, int *m, int *y){ int month, year = n / 365; int day = (n - year * 365) - LEAPYEARS(year >= 0 ? year - 1 : year); if (n < 0) { year--; while (day >= 0) { year++; day -= YEARDAYS(year); } day = YEARDAYS(year) + day; } else { while (day < 0) { year--; day += YEARDAYS(year); } } day++; for (month = 1; month <= 12; month++) { int days = MONTHDAYS(month, year); if (day <= days) break; day -= days; } if (n != int_nil) { *d = day; *m = month; *y = (year <= 0) ? year - 1 : year; /* HACK: hide year 0 */ } else { *d = *m = *y = int_nil; }}static INLINE daytimetotime(int hour, int min, int sec, int msec){ if (TIME(hour, min, sec, msec)) { return (daytime) (((((hour * 60) + min) * 60) + sec) * 1000 + msec); } return daytime_nil;}voidfromtime(int n, int *hour, int *min, int *sec, int *msec){ if (n != int_nil) { *hour = n / 3600000; n -= (*hour) * 3600000; *min = n / 60000; n -= (*min) * 60000; *sec = n / 1000; n -= (*sec) * 1000; *msec = n; } else { *hour = *min = *sec = *msec = int_nil; }}/* matches regardless of case and extra spaces */static INLINE intfleximatch(str s, str pat, int min){ int hit, spacy = 0; if (min == 0) { min = (int) strlen(pat); /* default mininum required hits */ } for (hit = 0; *pat; s++, hit++) { if (LOWER(*s) != *pat) { if (GDKisspace(*s) && spacy) { min++; continue; /* extra spaces */ } break; } spacy = GDKisspace(*pat); pat++; } return (hit >= min) ? hit : 0;}static INLINE intparse_substr(int *ret, str s, int min, str list[], int size){ int j = 0, i = 0; *ret = int_nil; while (++i <= size) { if ((j = fleximatch(s, list[i], min)) > 0) { *ret = i; break; } } return j;}static INLINE intdate_dayofweek(date v){ v %= 7; return (v <= 0) ? v + 7 : v;}#define SKIP_DAYS(d,w,i) d += i; w = (w + i)%7; if (w <= 0) w += 7;static INLINE datecompute_rule(rule *val, int y){ int m = val->s.month, cnt = ABS(val->s.day - DAY_ZERO); date d = todate(1, m, y); int dayofweek = date_dayofweek(d); int w = ABS(val->s.weekday - WEEKDAY_ZERO); if (val->s.weekday == WEEKDAY_ZERO) { /* cnt-th of month */ d += cnt - 1; } else if (val->s.day > DAY_ZERO) { if (val->s.weekday < WEEKDAY_ZERO) { /* first weekday on or after cnt-th of month */ SKIP_DAYS(d, dayofweek, cnt - 1); cnt = 1; } /* ELSE cnt-th weekday of month */ while (dayofweek != w || --cnt > 0) { if (++dayofweek == 8) dayofweek = 1; d++; } } else { if (val->s.weekday > WEEKDAY_ZERO) { /* cnt-last weekday from end of month */ SKIP_DAYS(d, dayofweek, MONTHDAYS(m, y) - 1); } else { /* first weekday on or before cnt-th of month */ SKIP_DAYS(d, dayofweek, cnt - 1); cnt = 1; } while (dayofweek != w || --cnt > 0) { if (--dayofweek == 0) dayofweek = 7; d--; } } return d;}static int dummy;#define BEFORE(d1,m1,d2,m2) (d1 < d2 || (d1 == d2 && m1 <= m2))int timestamp_add(timestamp *ret, timestamp *v, lng *msecs);static INLINE inttimestamp_inside(timestamp *ret, timestamp *t, tzone *z, lng offset){ /* starts with GMT time t, and returns whether it is in the DST for z */ lng add = (offset != (lng) 0) ? offset : (get_offset(z)) * (lng) 60000; int start_days, start_msecs, end_days, end_msecs, year; rule start, end; timestamp_add(ret, t, &add); if (ts_isnil(*ret) || z->dst == 0) { return 0; } set_rule(start, z->dst_start); set_rule(end, z->dst_end); start_msecs = start.s.minutes * 60000; end_msecs = end.s.minutes * 60000; fromdate((int) ret->days, &dummy, &dummy, &year); start_days = compute_rule(&start, year); end_days = compute_rule(&end, year); return BEFORE(start_days, start_msecs, end_days, end_msecs) ? (BEFORE(start_days, start_msecs, ret->days, ret->msecs) && BEFORE(ret->days, ret->msecs, end_days, end_msecs)) : (BEFORE(start_days, start_msecs, ret->days, ret->msecs) || BEFORE(ret->days, ret->msecs, end_days, end_msecs));}#line 1368 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"intdate_fromstr(str buf, int *len, date **d){ int day = 0, month = int_nil, year = 0, yearneg = (buf[0] == '-'), yearlast = 0, pos = 0, sep; if (*len < (int) sizeof(date)) { if (*d) GDKfree(*d); *d = (date *) GDKmalloc(*len = sizeof(date)); } **d = date_nil; if (yearneg == 0 && !GDKisdigit(buf[0])) { if (synonyms == 0) return 0; yearlast = 1; sep = ' '; } else { for (pos = yearneg; GDKisdigit(buf[pos]); pos++) { year = (buf[pos] - '0') + year * 10; if (year > YEAR_MAX) break; } sep = buf[pos++]; if (synonyms == 0 && sep != '-') { return 0; } sep = LOWER(sep); if (sep >= 'a' && sep <= 'z') { sep = 0; } else if (sep == ' ') { while (buf[pos] == ' ') pos++; } else if (sep != '-' && sep != '/' && sep != '\\') { return 0; /* syntax error */ } } if (GDKisdigit(buf[pos])) { month = buf[pos++] - '0'; if (GDKisdigit(buf[pos])) { month = (buf[pos++] - '0') + month * 10; } } else if (synonyms == 0) { return 0; } else { pos += parse_substr(&month, buf + pos, 3, MONTHS, 12); } if (month == int_nil || (sep && buf[pos++] != sep)) { return 0; /* syntax error */ } if (sep == ' ') { while (buf[pos] == ' ') pos++; } if (!GDKisdigit(buf[pos])) { return 0; /* syntax error */ } while (GDKisdigit(buf[pos])) { day = (buf[pos++] - '0') + day * 10; if (day > 31) break; } if (yearlast && buf[pos] == ',') { while (buf[++pos] == ' ') ; if (buf[pos] == '-') { yearneg = 1; pos++; } while (GDKisdigit(buf[pos])) { year = (buf[pos++] - '0') + year * 10; if (year > YEAR_MAX) break; } } /* handle semantic error here (returns nil in that case) */ **d = todate(day, month, yearneg ? -year : year); return pos;}intdate_tostr(str *buf, int *len, date *val){ int day, month, year; fromdate((int) *val, &day, &month, &year); /* longest possible string: "-5867411-01-01" i.e. 14 chars without NUL (see definition of YEAR_MIN/YEAR_MAX above) */ if (*len < 15) { if (*buf) GDKfree(*buf); *buf = (str) GDKmalloc(*len = 15); } if (*val == date_nil || !DATE(day, month, year)) { strcpy(*buf, "nil"); return 3; } sprintf(*buf, "%d-%02d-%02d", year, month, day); return (int) strlen(*buf);}#line 1469 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"intdaytime_fromstr(str buf, int *len, daytime **ret){ int hour, min, sec = 0, msec = 0, pos = 0; if (*len < (int) sizeof(daytime)) { if (*ret) GDKfree(*ret); *ret = (daytime *) GDKmalloc(*len = sizeof(daytime)); } **ret = daytime_nil; if (!GDKisdigit(buf[pos])) { return 0; /* syntax error */ } for (hour = 0; GDKisdigit(buf[pos]); pos++) { if (hour <= 24) hour = (buf[pos] - '0') + hour * 10; } if ((buf[pos++] != ':') || !GDKisdigit(buf[pos])) { return 0; /* syntax error */ } for (min = 0; GDKisdigit(buf[pos]); pos++) { if (min <= 60) min = (buf[pos] - '0') + min * 10; } if ((buf[pos] == ':') && GDKisdigit(buf[pos + 1])) { for (pos++, sec = 0; GDKisdigit(buf[pos]); pos++) { if (sec <= 60) sec = (buf[pos] - '0') + sec * 10; } if ((buf[pos] == '.' || (synonyms && buf[pos] == ':')) && GDKisdigit(buf[pos + 1])) { int fac = 100; for (pos++, msec = 0; GDKisdigit(buf[pos]); pos++) { msec += (buf[pos] - '0') * fac; fac /= 10; } } } /* handle semantic error here (returns nil in that case) */ **ret = totime(hour, min, sec, msec); return pos;}intdaytime_tz_fromstr(str buf, int *len, daytime **ret){ str s = buf; int pos = daytime_fromstr(s, len, ret); lng val, offset = 0; daytime mtime = 24 * 60 * 60 * 1000; if (!*ret || **ret == daytime_nil) return pos; s = buf + pos; pos = 0; while (GDKisspace(*s)) s++; /* incase of gmt we need to add the time zone */ if (fleximatch(s, "gmt", 0) == 3) { s += 3; } if ((s[0] == '-' || s[0] == '+') && GDKisdigit(s[1]) && GDKisdigit(s[2]) && GDKisdigit(s[pos = 4]) && ((s[3] == ':' && GDKisdigit(s[5])) || GDKisdigit(s[pos = 3]))) { offset = (((s[1] - '0') * (lng) 10 + (s[2] - '0')) * (lng) 60 + (s[pos] - '0') * (lng) 10 + (s[pos + 1] - '0')) * (lng) 60000; pos++; if (s[0] != '-') offset = -offset; s += pos; } else { /* if no tzone is specified; work with the local */ offset = get_offset(&tzone_local) * (lng) -60000; } val = **ret + offset; if (val < 0) val = mtime + val; if (val >= mtime) val = val - mtime; **ret = (daytime) val; return (int) (s - buf);}intdaytime_tostr(str *buf, int *len, daytime *val){ int hour, min, sec, msec; fromtime((int) *val, &hour, &min, &sec, &msec); if (*len < 12) { if (*buf) GDKfree(*buf); *buf = (str) GDKmalloc(*len = 13); } if (*val == daytime_nil || !TIME(hour, min, sec, msec)) { strcpy(*buf, "nil"); return 3; } sprintf(*buf, "%02d:%02d:%02d.%03d", hour, min, sec, msec); return 12;}#line 1572 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/modules/atoms/mtime.mx"inttimestamp_fromstr(str buf, int *len, timestamp **ret){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -