ref: d2e6790b3ff30aaa4a3a91e80334548155219d81
dir: /date.c/
#include <u.h> #include <libc.h> #include "date.h" int str2mon(char *s) { if(!strcmp(s, "Jan")) return 0; if(!strcmp(s, "Feb")) return 1; if(!strcmp(s, "Mar")) return 2; if(!strcmp(s, "Apr")) return 3; if(!strcmp(s, "May")) return 4; if(!strcmp(s, "Jun")) return 5; if(!strcmp(s, "Jul")) return 6; if(!strcmp(s, "Aug")) return 7; if(!strcmp(s, "Sep")) return 8; if(!strcmp(s, "Oct")) return 9; if(!strcmp(s, "Nov")) return 10; if(!strcmp(s, "Dec")) return 11; return 0; } int str2wday(char *s) { if(!strcmp(s, "Sun")) return 0; if(!strcmp(s, "Mon")) return 1; if(!strcmp(s, "Tue")) return 2; if(!strcmp(s, "Wed")) return 3; if(!strcmp(s, "Thu")) return 4; if(!strcmp(s, "Fri")) return 5; if(!strcmp(s, "Sat")) return 6; return 0; } int doty(int day, int month, int year) { int n, i; n = 0; for(i = 0; i < month; i++){ if(i == 0) n += 31; if(i == 1){ if(year%4 == 0 && year%100 == 0 && year%400 != 0) n += 29; else n += 28; } if(i == 2) n += 31; if(i == 3) n += 30; if(i == 4) n += 31; if(i == 5) n += 30; if(i == 6) n += 31; if(i == 7) n += 31; if(i == 8) n += 30; if(i == 9) n += 31; if(i == 10) n += 30; if(i == 11) n += 31; } n += day; return n; } long parseatomdate(char *input) { /* YYYY-MM-DDTHH:MM:SSZ */ /* YYYY year */ /* MM month */ /* DD day of month */ /* T or space */ /* HH hour */ /* MM minute */ /* SS seconds */ /* .SS seconds (sub, optional) */ /* Z zulu (UTC+0) */ /* +HH:MM tz offset */ /* examples: length */ /* 2020-06-05( |T)13:20:35.44+04:00 28 */ /* 2020-06-05( |T)13:20:35+04:00 25 */ /* 2020-06-05( |T)13:20:35.44Z 23 */ /* 2020-06-05( |T)13:20:35Z 20 */ Tm ret; char *args[9]; char s[32]; int n; strcpy(s, input); switch(strlen(s)){ case 28: n = getfields(s, args, 9, 1, "- T:.+Z"); if(n != 9) sysfatal("error parsing atom date: %d", n); ret.year = atoi(args[0]) - 1900; ret.mon = atoi(args[1]) - 1; ret.mday = atoi(args[2]); ret.tzoff = atoi(args[7]); ret.hour = atoi(args[3]); ret.min = atoi(args[4]); ret.sec = atoi(args[5]); break; case 25: n = getfields(s, args, 8, 1, "- T:.+Z"); if(n != 8) sysfatal("error parsing atom date: %d", n); ret.year = atoi(args[0]) - 1900; ret.mon = atoi(args[1]) - 1; ret.mday = atoi(args[2]); ret.tzoff = atoi(args[6]); ret.hour = atoi(args[3]); ret.min = atoi(args[4]); ret.sec = atoi(args[5]); break; case 23: n = getfields(s, args, 7, 1, "- T:.+Z"); if(n != 7) sysfatal("error parsing atom date: %d", n); ret.year = atoi(args[0]) - 1900; ret.mon = atoi(args[1]); ret.mday = atoi(args[2]); ret.tzoff = 0; ret.hour = atoi(args[3]); ret.min = atoi(args[4]); ret.sec = atoi(args[5]); break; case 20: n = getfields(s, args, 6, 1, "- T:.+Z"); if(n != 6) sysfatal("error parsing atom date: %d", n); ret.year = atoi(args[0]) - 1900; ret.mon = atoi(args[1]) - 1; ret.mday = atoi(args[2]); ret.tzoff = 0; ret.hour = atoi(args[3]); ret.min = atoi(args[4]); ret.sec = atoi(args[5]); break; default: sysfatal("error parsing atom date format: %s", s); } ret.yday = doty(ret.mday, ret.mon, ret.year); return tm2sec(&ret) - ret.tzoff*60*60; } long parsedate(char *s) { Tm ret; char input[64]; char *args[8]; int n, i; strcpy(input, s); n = getfields(input, args, 8, 1, ", :"); if(n < 8){ /* try parsing atom date */ return parseatomdate(s); } for(i = 0; i < n; i++){ if(!args[i]) sysfatal("error parsing pubDate: %s", s); switch(i){ case 0: /* day of the week */ ret.wday = str2wday(args[i]); break; case 1: /* day of the month */ ret.mday = atoi(args[i]); break; case 2: /* month of the year */ ret.mon = str2mon(args[i]); break; case 3: /* year */ ret.year = atoi(args[i]) - 1900; break; case 4: /* hour */ ret.hour = atoi(args[i]); break; case 5: /* minute */ ret.min = atoi(args[i]); break; case 6: /* second */ ret.sec = atoi(args[i]); break; case 7: /* timezone offset */ ret.tzoff = atoi(args[i])/100; break; } } ret.yday = doty(ret.mday, ret.mon, ret.year); return tm2sec(&ret) - ret.tzoff*60*60; }