| top | |
static const double J0000 = 1721424.5; // Julian date of Gregorian epoch: 0000-01-01
static const double J1970 = 2440587.5; // Julian date at Unix epoch: 1970-01-01
static const double JMJD = 2400000.5; // Epoch of Modified Julian Date system
static const double J1900 = 2415020.5; // Epoch (day 1) of Excel 1900 date system (PC)
static const double J1904 = 2416480.5; // Epoch (day 0) of Excel 1904 date system (Mac)
/* MOD -- Modulus function which works for non-integers. */
static double mod(double a,double b) {
return a - (b * floor(a / b));
}
// AMOD -- Modulus function which returns numerator if modulus is zero
static double amod(double a,double b) {
return mod(a - 1, b) + 1;
}
// JWDAY -- Calculate day of week from Julian day
static int jwday(double j) {
return mod((j + 1.5),7);
}
static long nextLong(chars r,chars *v) {
if (r) {
while (!isdigit(*r) && *r) r++;
if (!*r) r = 0;
}
long x = r ? strtol(r,v,10) : 0;
if (!r && v) *v = 0;
return x;
}
static long long nextWideInt(chars r,chars *v) {
if (r) {
while (!isdigit(*r) && *r) r++;
if (!*r) r = 0;
}
long long x = r ? strtoll(r,v,10) : 0;
if (!r && v) *v = 0;
return x;
}
<Day of week utilities>
<Durations calendar>
<Gregorian calendar>
<ISO week calendar>
<ISO day of year calendar>
<Julian day number>
<Julian (Roman) calendar>
<Hebrew calendar>
<Islamic lunar calendar>
<Persian calendar>
<Mayan calendars>
<Bahai calendar>
<Indian civil calendar>
<Discordian calendar>
<Easter (3WY)>
<Convert from calendar to date-time (3WY)>
<Convert from date-time to calendar (3WY)>
Calendar conversions.Gregorian.Gregorian calendar Easter. |
| ^ | Referenced at: 2, 6, 9, 90. | | | | | section top | | | ^ | | | | | | section top | |
case o_clock:
if (N==3) {
Obj rs = wyrm_tiktokFromCalendar(intr,P[2]);
if (rs) {Tcl_SetObjResult(intr,rs); return TCL_OK;}
else return TCL_ERROR;
}else {
Tcl_WrongNumArgs(intr,2,P,"date-time-1 date-time-2");
return TCL_ERROR;
}
case o_calendar:
if (N==4) {
long type = wyrm_stringToC(Tcl_GetString(P[3]));
Obj rs = wyrm_tiktokToCalendar(intr,P[2],type);
if (rs) {Tcl_SetObjResult(intr,rs); return TCL_OK;}
else return TCL_ERROR;
}else {
Tcl_WrongNumArgs(intr,2,P,"date-time-1 date-time-2");
return TCL_ERROR;
}
| ^ | | | | | | section top | |
Obj wyrm_tiktokFromCalendar(Intr intr,Obj calendar) {
chars p = Tcl_GetString(calendar);
int k; long type = 0;
for (k=1; k<=4 && isalpha(*p); k++,p++) type = (type<<8)|(*p&0xFF);
int leap = nextLong(p,&p);
double jdate = 0; long long extraseconds = 0;
switch (type) {
<Convert from calendar to date-time>
default: rprintf(intr,"unknown calendar type: %{i}s",type); return 0;
}
long long jdsecs = floor(jdate*secondsPerDay);
int hours = nextLong(p,&p);
int minutes = nextLong(p,&p);
int seconds = nextLong(p,0);
jdsecs += 3600*hours + 60*minutes + seconds + extraseconds;
TimeValue t = {jdsecs,'JDAY'};
return encodeObj(t);
}
| ^ | | | | | | section top | |
Obj wyrm_tiktokToCalendar(Intr intr,Obj datetime,long type) {
TimeValue t; if (decodeObj(intr,datetime,&t)!=TCL_OK) return 0;
long long o; double jdate; char r[500];
long long jdsecs = t.seconds; bool standardclock = true;
if (t.base==0) goto duration;
if (baseRelation(intr,t.base,&o,'JDAY')!=TCL_OK) return 0;
jdate = ((double)(t.seconds+o))/secondsPerDay;
jdsecs += o;
switch (type) {
<Convert from date-time to calendar>
default: rprintf(intr,"unknown calendar type: %{i}s",type); return 0;
}
if (standardclock) {
int secs = jdsecs % secondsPerDay;
if (secs<0) secs += secondsPerDay;
int hours = secs/3600;
int minutes = (secs/60)%60;
secs = secs%60;
sprintf(r+strlen(r),".%d.%d.%d",hours,minutes,secs);
}
return Tcl_NewStringObj(r,-1);
}
| ^ | | | | | | section top | |
Obj wyrm_tiktokFromCalendar(Intr,Obj);
Obj wyrm_tiktokToCalendar(Intr,Obj,long type);
| ^ | Definition continued at: 85. | | | | | section top | |
/* WEEKDAY_BEFORE -- Return Julian date of given weekday (0 = Sunday)
in the seven days ending on jd. */
static int weekday_before(int weekday,double jd) {
return jd - jwday(jd - weekday);
}
/* SEARCH_WEEKDAY -- Determine the Julian date for:
weekday Day of week desired, 0 = Sunday
jd Julian date to begin search
direction 1 = next weekday, -1 = last weekday
offset Offset from jd to begin search
*/
static int search_weekday(int weekday,double jd, int direction, int offset) {
return weekday_before(weekday, jd + (direction * offset));
}
// Utility weekday functions, just wrappers for search_weekday
static int nearest_weekday(int weekday,double jd) {
return search_weekday(weekday, jd, 1, 3);
}
static int next_weekday(int weekday,double jd) {
return search_weekday(weekday, jd, 1, 7);
}
static int next_or_current_weekday(int weekday,double jd) {
return search_weekday(weekday, jd, 1, 6);
}
static int previous_weekday(int weekday,double jd) {
return search_weekday(weekday, jd, -1, 1);
}
static int previous_or_current_weekday(int weekday,double jd) {
return search_weekday(weekday, jd, 1, 0);
}
| ^ | | | | | | section top | | | ^ | | | | | | section top | |
case 'dura': {
long long day = nextWideInt(p,&p);
int hours = nextLong(p,&p);
int minutes = nextLong(p,&p);
int seconds = nextLong(p,0);
TimeValue t = {secondsPerDay*day + 3600*hours + 60*minutes + seconds,0};
return encodeObj(t);
}
| ^ | Definition continued at: 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80. | | | | | section top | |
duration: {
jdsecs = t.seconds;
sprintf(r,"dura.0.%lld",jdsecs/secondsPerDay);
} break;
| ^ | Definition continued at: 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81. | | | | | section top | |
// LEAP_GREGORIAN -- Is a given year in the Gregorian calendar a leap year ?
static bool leap_gregorian(long long year) {
return ((year % 4) == 0) && (!(((year % 100) == 0) && ((year % 400) != 0)));
}
// GREGORIAN_TO_JD -- Determine Julian day number from Gregorian calendar date
static const double GREGORIAN_EPOCH = 1721425.5;
static double gregorian_to_jd(long year,long month,long day) {
return (GREGORIAN_EPOCH - 1)
+ (365 * (year - 1))
+ floor((year - 1) / 4.0)
- floor((year - 1) / 100.0)
+ floor((year - 1) / 400.0)
+ floor((((367 * month) - 362) / 12)
+ ((month <= 2) ? 0 : (leap_gregorian(year) ? -1 : -2))
+ day);
}
// JD_TO_GREGORIAN -- Calculate Gregorian calendar date from Julian day
static void jd_to_gregorian(double jd,long long *year,long *month,long *day) {
double wjd = floor(jd - 0.5) + 0.5;
long long depoch = wjd - GREGORIAN_EPOCH;
long long quadricent = floor(depoch / 146097.0);
long long dqc = mod(depoch, 146097.0);
long long cent = floor(dqc / 36524.0);
long long dcent = mod(dqc, 36524.0);
long long quad = floor(dcent / 1461.0);
long long dquad = mod(dcent, 1461.0);
int yindex = floor(dquad / 365.0);
long long y = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex;
if (!((cent == 4) || (yindex == 4))) y++;
long yearday = wjd - gregorian_to_jd(y, 1, 1);
long leapadj = (wjd < gregorian_to_jd(y, 3, 1)) ? 0 : leap_gregorian(y) ? 1 : 2;
long m = floor((((yearday + leapadj) * 12.0) + 373) / 367);
long d = (wjd - gregorian_to_jd(y,m,1)) + 1;
*year = y;
*month = m;
*day = d;
}
| ^ | | | | | | section top | |
case 'GREG': {
long long year = nextWideInt(p,&p);
long month = nextLong(p,&p);
long day = nextLong(p,&p);
if (year<0) ++year;
jdate = gregorian_to_jd(year,month,day);
} break;
| ^ | Definition continued at: 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80. | | | | | section top | |
case 'GREG': {
long long year; long month,day; jd_to_gregorian(jdate,&year,&month,&day);
if (year<=0) --year;
sprintf(r,"GREG.%d.%lld.%ld.%ld",leap_gregorian(year),year,month,day);
jdsecs += halfDay;
} break;
| ^ | Definition continued at: 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81. | | | | | section top | |
// ISO_TO_JULIAN -- Return Julian day of given ISO year, week, and day
static int n_weeks(int weekday,double jd,int nthweek) {
int j = 7 * nthweek;
if (nthweek > 0) {
j += previous_weekday(weekday, jd);
} else {
j += next_weekday(weekday, jd);
}
return j;
}
static double iso_to_julian(long long year,long week,long day) {
return day + n_weeks(0, gregorian_to_jd(year - 1, 12, 28), week);
}
// JD_TO_ISO -- Return array of ISO (year, week, day) for Julian day
static void jd_to_iso(double jd,long long *year,long *week,long *day) {
long month,w,d; long long y;
jd_to_gregorian(jd - 3,&y,&month,&d);
if (jd >= iso_to_julian(y + 1, 1, 1)) (y)++;
w = floor((jd - iso_to_julian(y, 1, 1)) / 7) + 1;
d = jwday(jd);
if (d == 0) d = 7;
*year = y;
*week = w;
*day = d;
}
| ^ | | | | | | section top | |
case 'ISOW': {
long long year = nextWideInt(p,&p);
int week = nextLong(p,&p);
long day = nextLong(p,&p);
if (year<0) ++year;
jdate = iso_to_julian(year,week,day) + 0.5;
} break;
| ^ | | | | | | section top | |
case 'ISOW': {
long long year; long week,day; jd_to_iso(jdate,&year,&week,&day);
sprintf(r,"ISOW.0.%lld.%ld.%ld",year,week,day);
jdsecs += halfDay;
} break;
| ^ | | | | | | section top | |
// ISO_DAY_TO_JULIAN -- Return Julian day of given ISO year, and day of year
static double iso_day_to_julian(long long year,long day) {
return (day - 1) + gregorian_to_jd(year, 1, 1);
}
// JD_TO_ISO_DAY -- Return array of ISO (year, day_of_year) for Julian day
static void jd_to_iso_day(double jd,long long *year,long *day) {
long long y; long month,d;
jd_to_gregorian(jd,&y,&month,&d);
d = floor(jd - gregorian_to_jd(y, 1, 1)) + 1;
*year = y;
*day = d;
}
| ^ | | | | | | section top | |
case 'ISOD': {
long long year = nextWideInt(p,&p);
long day = nextLong(p,&p);
jdate = iso_day_to_julian(year,day);
} break;
| ^ | | | | | | section top | |
case 'ISOD': {
long long year; long day; jd_to_iso_day(jdate,&year,&day);
sprintf(r,"ISOD.0.%lld.%ld",year,day);
jdsecs += halfDay;
} break;
| ^ | | | | | | section top | | | ^ | | | | | | section top | |
case 'JDAY': {
long long daynumber = nextWideInt(p,&p);
jdate |
|