// date.c #include "common.h" #include "cstring.h" #include "cyber.h" #include "disk.h" #include "floating.h" #include "calend.h" #include "date.h" // Time stored as a ulong is stored in Mac system format, which is the number of // seconds since 12:00 a.m., Jan 1, 1904. // Date and time functions static char Calends[]={ 0,3,2,5,0,3,5,1,4,6,2,4 }; int gregdayofweek(int AD, int MONTH, int DATE) { if (MONTH<2) AD--; // This algorithm was not written by me return (AD + (AD/4) - (AD/100) + (AD/400) + Calends[MONTH] + DATE) % 7; } ulong secssince1904(int YEAR, int MONTH, int DATE, int HOUR) { DateTimeRec D; ulong T; D.year=YEAR; D.month= MONTH + 1; D.day= DATE + 1; D.hour=HOUR; D.minute=0; D.second=0; DateToSeconds(&D,&T); return T; } ulong currentgmt(void) { ulong U; MachineLocation ML; long L; ReadLocation(&ML); L= (ML.u.gmtDelta << 8) >> 8; GetDateTime(&U); return U - L; } void incrementtime(ulong *TIME, char UNIT, long NUM, bool Round) { DateTimeRec D; if (!TIME) return; switch (UNIT) { // breaks intentionally omitted case 'w': NUM*=7; case 'd': NUM*=24; case 'h': NUM*=60; case 'm': NUM*=60; case 's': (*TIME)+=NUM; if (!Round) return; SecondsToDate(*TIME,&D); break; case 'M': case 'y': SecondsToDate(*TIME,&D); if (UNIT=='y') D.year+=NUM; else { D.month+= NUM - 1; D.year+= D.month / 12; D.month%=12; if (D.month<0) { D.month+=12; D.year--; } D.month++; } if (!Round) { DateToSeconds(&D,TIME); return; } break; default: return; } switch (UNIT) { // breaks intentionally omitted case 'w': D.day-= D.dayOfWeek - 1; case 'd': D.hour=0; case 'h': D.minute=0; case 'm': D.second=0; break; case 'y': D.month=1; case 'M': D.day=1; D.hour=0; D.minute=0; D.second=0; } DateToSeconds(&D,TIME); } // Date and time strings string timestring(ulong TIME) { DateTimeRec D; char *S; SecondsToDate(TIME,&D); S=cat3(5,fig(D.hour),D.minute<10 ? ":0" : ":",fig(D.minute)); return cat3(5,S,D.second<10 ? ":0" : ":",fig(D.second)); } string datestring(ulong TIME, bool WeekDay) { DateTimeRec D; char *S; SecondsToDate(TIME,&D); S=cat5(17,fig(D.year)," ",monthname(D.month - 1)," ",fig(D.day)); return WeekDay ? cat3(1,S,", ",dayname(D.dayOfWeek - 1)) : S; } // Parsing date strings bool parseepoch(const char *S, ulong *TIME) { long Q; DateTimeRec D; if (!S || !TIME) return 0; while (*S==' ') S++; if (!parseinteger(S,&Q)) return 0; while (numeral(*S)) S++; if (*(S++)!='.') return 0; if (*(S++)!='0') return 0; if (numeral(*S)) return 0; if (Q<1905 || Q>2040) return 0; D.year= Q - 1; D.month=12; D.day=31; // ? confirm D.hour=0; D.minute=0; D.second=0; DateToSeconds(&D,TIME); return 1; } bool parsejuliandate(const char *S, ulong *TIME) { long Q; if (!S || !TIME) return 0; while (*S==' ') S++; if (!parseinteger(S,&Q)) return 0; while (numeral(*S)) S++; if (*(S++)!='.') return 0; if (*(S++)!='5') return 0; if (numeral(*S)) return 0; Q-=2416480; if (Q<0) return 0; *TIME= Q * (ulong)86400L; return 1; } bool parsenoraddate(const char *S, ulong *TIME) { real Q; char C; DateTimeRec D; if (!S || !TIME) return 0; while (*S==' ') S++; D.year=1900; if (!numeral(C=S[0])) return 0; D.year+= 10 * (C - '0'); if (!numeral(C=S[1])) return 0; D.year+= C - '0'; if (D.year<=1940) D.year+=100; S+=2; if (!parsereal(S,&Q)) return 0; D.month=1; D.day=(int)Q; Q-=D.day; Q*=24.0; D.hour=(int)Q; Q-=D.hour; Q*=60.0; D.minute=(int)Q; Q-=D.minute; Q*=60.0; D.second=(int)Q; DateToSeconds(&D,TIME); return 1; }