void fh_debug(FILE *stream, js_val *val, int indent, bool newline) { switch (val->type) { case T_BOOLEAN: fprintf(stream, "%s", !val->boolean.val ? "false" : "true"); break; case T_NUMBER: debug_num(stream, val); break; case T_STRING: if (fh->opt_interactive) cfprintf(stream, ANSI_YELLOW, "'%s'", val->string.ptr); else fprintf(stream, "%s", val->string.ptr); break; case T_NULL: cfprintf(stream, ANSI_GRAY, "null"); break; case T_UNDEF: cfprintf(stream, ANSI_GRAY, "undefined"); break; case T_OBJECT: if (IS_ARR(val)) debug_arr(stream, val, indent); else if (IS_FUNC(val)) cfprintf(stream, ANSI_BLUE, "[Function]"); else if (IS_DATE(val)) fprintf(stream, "[Date %ld]", (long)val->object.primitive->number.val); else debug_obj(stream, val, indent, false); break; } if (newline) fprintf(stream, "\n"); }
*/ REBINT PD_Date(REBPVS *pvs) /* ***********************************************************************/ { REBVAL *data = pvs->value; REBVAL *arg = pvs->select; REBVAL *val = pvs->setval; REBINT i; REBINT n; REBI64 secs; REBINT tz; REBDAT date; REBCNT day, month, year; REBINT num; REBVAL dat; REB_TIMEF time; // !zone! - adjust date by zone (unless /utc given) if (IS_WORD(arg)) { //!!! change this to an array!? switch (VAL_WORD_CANON(arg)) { case SYM_YEAR: i = 0; break; case SYM_MONTH: i = 1; break; case SYM_DAY: i = 2; break; case SYM_TIME: i = 3; break; case SYM_ZONE: i = 4; break; case SYM_DATE: i = 5; break; case SYM_WEEKDAY: i = 6; break; case SYM_JULIAN: case SYM_YEARDAY: i = 7; break; case SYM_UTC: i = 8; break; case SYM_HOUR: i = 9; break; case SYM_MINUTE: i = 10; break; case SYM_SECOND: i = 11; break; default: return PE_BAD_SELECT; } } else if (IS_INTEGER(arg)) { i = Int32(arg) - 1; if (i < 0 || i > 8) return PE_BAD_SELECT; } else return PE_BAD_SELECT; if (IS_DATE(data)) { dat = *data; // recode! data = &dat; if (i != 8) Adjust_Date_Zone(data, FALSE); // adjust for timezone date = VAL_DATE(data); day = VAL_DAY(data) - 1; month = VAL_MONTH(data) - 1; year = VAL_YEAR(data); secs = VAL_TIME(data); tz = VAL_ZONE(data); if (i > 8) Split_Time(secs, &time); } else { Trap_Arg_DEAD_END(data); // this should never happen } if (val == 0) { val = pvs->store; switch(i) { case 0: num = year; break; case 1: num = month + 1; break; case 2: num = day + 1; break; case 3: if (secs == NO_TIME) return PE_NONE; *val = *data; VAL_SET(val, REB_TIME); return PE_USE; case 4: if (secs == NO_TIME) return PE_NONE; *val = *data; VAL_TIME(val) = (i64)tz * ZONE_MINS * MIN_SEC; VAL_SET(val, REB_TIME); return PE_USE; case 5: // date *val = *data; VAL_TIME(val) = NO_TIME; VAL_ZONE(val) = 0; return PE_USE; case 6: // weekday num = Week_Day(date); break; case 7: // yearday num = (REBINT)Julian_Date(date); break; case 8: // utc *val = *data; VAL_ZONE(val) = 0; return PE_USE; case 9: num = time.h; break; case 10: num = time.m; break; case 11: if (time.n == 0) num = time.s; else { SET_DECIMAL(val, (REBDEC)time.s + (time.n * NANO)); return PE_USE; } break; default: return PE_NONE; } SET_INTEGER(val, num); return PE_USE; } else { if (IS_INTEGER(val) || IS_DECIMAL(val)) n = Int32s(val, 0); else if (IS_NONE(val)) n = 0; else if (IS_TIME(val) && (i == 3 || i == 4)); else if (IS_DATE(val) && (i == 3 || i == 5)); else return PE_BAD_SET_TYPE; switch(i) { case 0: year = n; break; case 1: month = n - 1; break; case 2: day = n - 1; break; case 3: // time if (IS_NONE(val)) { secs = NO_TIME; tz = 0; break; } else if (IS_TIME(val) || IS_DATE(val)) secs = VAL_TIME(val); else if (IS_INTEGER(val)) secs = n * SEC_SEC; else if (IS_DECIMAL(val)) secs = DEC_TO_SECS(VAL_DECIMAL(val)); else return PE_BAD_SET_TYPE; break; case 4: // zone if (IS_TIME(val)) tz = (REBINT)(VAL_TIME(val) / (ZONE_MINS * MIN_SEC)); else if (IS_DATE(val)) tz = VAL_ZONE(val); else tz = n * (60 / ZONE_MINS); if (tz > MAX_ZONE || tz < -MAX_ZONE) return PE_BAD_RANGE; break; case 5: // date if (!IS_DATE(val)) return PE_BAD_SET_TYPE; date = VAL_DATE(val); goto setDate; case 9: time.h = n; secs = Join_Time(&time, FALSE); break; case 10: time.m = n; secs = Join_Time(&time, FALSE); break; case 11: if (IS_INTEGER(val)) { time.s = n; time.n = 0; } else { //if (f < 0.0) Trap_Range_DEAD_END(val); time.s = (REBINT)VAL_DECIMAL(val); time.n = (REBINT)((VAL_DECIMAL(val) - time.s) * SEC_SEC); } secs = Join_Time(&time, FALSE); break; default: return PE_BAD_SET; } Normalize_Time(&secs, &day); date = Normalize_Date(day, month, year, tz); setDate: data = pvs->value; VAL_SET(data, REB_DATE); VAL_DATE(data) = date; VAL_TIME(data) = secs; Adjust_Date_Zone(data, TRUE); return PE_USE; } }
*/ REBFLG MT_Date(REBVAL *val, REBVAL *arg, REBCNT type) /* ** Given a block of values, construct a date datatype. ** ***********************************************************************/ { REBI64 secs = NO_TIME; REBINT tz = 0; REBDAT date; REBCNT year, month, day; if (IS_DATE(arg)) { *val = *arg; return TRUE; } if (!IS_INTEGER(arg)) return FALSE; day = Int32s(arg++, 1); if (!IS_INTEGER(arg)) return FALSE; month = Int32s(arg++, 1); if (!IS_INTEGER(arg)) return FALSE; if (day > 99) { year = day; day = Int32s(arg++, 1); } else year = Int32s(arg++, 0); if (month < 1 || month > 12) return FALSE; if (year > MAX_YEAR || day < 1 || day > Month_Max_Days[month-1]) return FALSE; // Check February for leap year or century: if (month == 2 && day == 29) { if (((year % 4) != 0) || // not leap year ((year % 100) == 0 && // century? (year % 400) != 0)) return FALSE; // not leap century } day--; month--; if (IS_TIME(arg)) { secs = VAL_TIME(arg); arg++; } if (IS_TIME(arg)) { tz = (REBINT)(VAL_TIME(arg) / (ZONE_MINS * MIN_SEC)); if (tz < -MAX_ZONE || tz > MAX_ZONE) Trap_Range_DEAD_END(arg); arg++; } if (!IS_END(arg)) return FALSE; Normalize_Time(&secs, &day); date = Normalize_Date(day, month, year, tz); VAL_SET(val, REB_DATE); VAL_DATE(val) = date; VAL_TIME(val) = secs; Adjust_Date_Zone(val, TRUE); return TRUE; }