*/ void Emit_Time(REB_MOLD *mold, const REBVAL *value) /* ***********************************************************************/ { REB_TIMEF tf; const char *fmt; Split_Time(VAL_TIME(value), &tf); // loses sign if (tf.s == 0 && tf.n == 0) fmt = "I:2"; else fmt = "I:2:2"; if (VAL_TIME(value) < (REBI64)0) Append_Byte(mold->series, '-'); Emit(mold, fmt, tf.h, tf.m, tf.s, 0); if (tf.n > 0) Emit(mold, ".i", tf.n); }
// // Emit_Time: C // void Emit_Time(REB_MOLD *mold, const REBVAL *value) { REB_TIMEF tf; const char *fmt; Split_Time(VAL_TIME(value), &tf); // loses sign if (tf.s == 0 && tf.n == 0) fmt = "I:2"; else fmt = "I:2:2"; if (VAL_TIME(value) < cast(REBI64, 0)) Append_Codepoint_Raw(mold->series, '-'); Emit(mold, fmt, tf.h, tf.m, tf.s, 0); if (tf.n > 0) Emit(mold, ".i", tf.n); }
*/ REBINT PD_Time(REBPVS *pvs) /* ***********************************************************************/ { REBVAL *val; REBINT i; REBINT n; REBDEC f; REB_TIMEF tf; if (IS_WORD(pvs->select)) { switch (VAL_WORD_CANON(pvs->select)) { case SYM_HOUR: i = 0; break; case SYM_MINUTE: i = 1; break; case SYM_SECOND: i = 2; break; default: return PE_BAD_SELECT; } } else if (IS_INTEGER(pvs->select)) i = VAL_INT32(pvs->select) - 1; else return PE_BAD_SELECT; Split_Time(VAL_TIME(pvs->value), &tf); // loses sign if (!(val = pvs->setval)) { val = pvs->store; switch(i) { case 0: // hours SET_INTEGER(val, tf.h); break; case 1: SET_INTEGER(val, tf.m); break; case 2: if (tf.n == 0) SET_INTEGER(val, tf.s); else SET_DECIMAL(val, (REBDEC)tf.s + (tf.n * NANO)); break; default: return PE_NONE; } return PE_USE; } else { if (IS_INTEGER(val) || IS_DECIMAL(val)) n = Int32s(val, 0); else if (IS_NONE(val)) n = 0; else return PE_BAD_SET; switch(i) { case 0: tf.h = n; break; case 1: tf.m = n; break; case 2: if (IS_DECIMAL(val)) { f = VAL_DECIMAL(val); if (f < 0.0) Trap_Range_DEAD_END(val); tf.s = (REBINT)f; tf.n = (REBINT)((f - tf.s) * SEC_SEC); } else { tf.s = n; tf.n = 0; } break; default: return PE_BAD_SELECT; } VAL_TIME(pvs->value) = Join_Time(&tf, FALSE); return PE_OK; } }
*/ 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; } }