caddr_t arithm_dt_subtract (ccaddr_t box1, ccaddr_t box2, caddr_t *err_ret) { dtp_t dtp1 = DV_TYPE_OF (box1), dtp2 = DV_TYPE_OF (box2); if ((DV_DATETIME == dtp1) && (DV_DATETIME == dtp2)) { boxint s1 = DT_CAST_TO_TOTAL_SECONDS(box1); boxint s2 = DT_CAST_TO_TOTAL_SECONDS(box2); int frac1 = DT_FRACTION(box1); int frac2 = DT_FRACTION(box2); if (frac1 == frac2) return box_num (s1 - s2); else { numeric_t res = numeric_allocate (); numeric_from_int64 (res, ((s1 - s2) * 1000000000L) + (frac1 - frac2)); res->n_len -= 9; res->n_scale += 9; return (caddr_t)res; } } if ((DV_DATETIME == dtp1) && ((DV_LONG_INT == dtp2) || (DV_DOUBLE_FLOAT == dtp2) || (DV_NUMERIC == dtp2))) { caddr_t res = arithm_dt_add_num (box1, box2, 1, err_ret); if (NULL != err_ret) return res; if (NULL == res) goto generic_err; return res; } generic_err: err_ret[0] = srv_make_new_error ("22003", "SR087", "Wrong arguments for datetime arithmetic, can not subtract value of type %d (%s) from value type %d (%s).", dtp2, dv_type_title (dtp2), dtp1, dv_type_title (dtp1) ); return NULL; }
caddr_t bif_date_diff (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t unit = bif_string_arg (qst, args, 0, "datediff"); caddr_t dt1 = bif_date_arg (qst, args, 1, "datediff"); caddr_t dt2 = bif_date_arg (qst, args, 2, "datediff"); boxint s1 = (boxint)DT_DAY (dt1) * 24 * 60 * 60 + (boxint)DT_HOUR (dt1) * 60 * 60 + (boxint)DT_MINUTE (dt1) * 60 + DT_SECOND (dt1); boxint s2 = (boxint)DT_DAY (dt2) * 24 * 60 * 60 + (boxint)DT_HOUR (dt2) * 60 * 60 + (boxint)DT_MINUTE (dt2) * 60 + DT_SECOND (dt2); int frac1, frac2; int diffyear, diffmonth; if (0 == stricmp (unit, "day")) return box_num ((boxint)DT_DAY (dt2) - (boxint)DT_DAY (dt1)); if (0 == stricmp (unit, "hour")) return box_num ((s2 - s1) / (60 * 60)); if (0 == stricmp (unit, "minute")) return box_num ((s2 - s1) / 60); if (0 == stricmp (unit, "second")) return box_num (s2 - s1); diffyear = !stricmp (unit, "year"); diffmonth = (diffyear ? 0 : !stricmp (unit, "month")); if (diffyear || diffmonth) { TIMESTAMP_STRUCT ts1; TIMESTAMP_STRUCT ts2; int tz_tweak = DT_TZ (dt1); dt_to_GMTimestamp_struct (dt2, &ts2); dt_to_GMTimestamp_struct (dt1, &ts1); ts_add (&ts1, tz_tweak, "minute"); ts_add (&ts2, tz_tweak, "minute"); if (diffyear) return box_num ((boxint)ts2.year - (boxint)ts1.year); if (diffmonth) return box_num ((boxint)(ts2.year * 12 + ts2.month) - (boxint)(ts1.year * 12 + ts1.month)); } frac1 = DT_FRACTION(dt1); frac2 = DT_FRACTION(dt2); if (0 == stricmp (unit, "millisecond")) return box_num ((s2 - s1) * (boxint)1000 + (frac2 / 1000000 - frac1 / 1000000)); if (0 == stricmp (unit, "microsecond")) return box_num ((s2 - s1) * (boxint)1000000 + (frac2 / 1000 - frac1 / 1000)); if (0 == stricmp (unit, "nanosecond")) return box_num ((s2 - s1) * (boxint)1000000000 + (frac2 - frac1)); sqlr_new_error ("22023", "DT002", "Bad unit in datediff: %s.", unit); return NULL; }
caddr_t bif_nasa_tjd_fraction (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t arg = bif_date_arg (qst, args, 0, "nasa_tjd_fraction"); double f = (((DT_HOUR (arg) * (boxint)60 + DT_MINUTE (arg)) * (boxint)60 + DT_SECOND (arg)) * (boxint)1000000 + DT_FRACTION (arg)) / (60*60*24*1000000.0); return box_double (f); }