caddr_t bif_merge_nasa_tjd_to_datetime (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { boxint num = bif_long_arg (qst, args, 0, "merge_nasa_tjd_to_datetime"); caddr_t res = dk_alloc_box_zero (DT_LENGTH, DV_DATETIME); DT_SET_DAY (res, num + NASA_TJD_OFFSET); if (1 < BOX_ELEMENTS (args)) { double frac = bif_double_arg (qst, args, 1, "merge_nasa_tjd_to_datetime"); boxint frac_microsec = frac * (60*60*24*1000000.0); if ((0 > frac_microsec) || (60*60*24*(boxint)(1000000) <= frac_microsec)) sqlr_new_error ("22023", "SR644", "Fraction of julian day should be nonnegative and less than 1"); DT_SET_FRACTION (res, (frac_microsec % 1000000) * 1000); frac_microsec = frac_microsec / 1000000; DT_SET_SECOND (res, (frac_microsec % 60)); frac_microsec = frac_microsec / 60; DT_SET_MINUTE (res, (frac_microsec % 60)); frac_microsec = frac_microsec / 60; DT_SET_HOUR (res, frac_microsec); DT_SET_DT_TYPE (res, DT_TYPE_DATETIME); } else DT_SET_DT_TYPE (res, DT_TYPE_DATE); return res; }
caddr_t bif_dateadd (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t res; caddr_t part = bif_string_arg (qst, args, 0, "dateadd"); boxint n = bif_long_arg (qst, args, 1, "dateadd"); caddr_t dt = bif_date_arg (qst, args, 2, "dateadd"); TIMESTAMP_STRUCT ts; int dt_type = DT_DT_TYPE (dt); int year_or_month_tz_tweak = (((!strcmp ("year", part)) || (!strcmp ("month", part))) ? DT_TZ (dt) : 0); DT_AUDIT_FIELDS (dt); dt_to_GMTimestamp_struct (dt, &ts); if (year_or_month_tz_tweak) ts_add (&ts, year_or_month_tz_tweak, "minute"); ts_add (&ts, n, part); if (year_or_month_tz_tweak) ts_add (&ts, -year_or_month_tz_tweak, "minute"); res = dk_alloc_box (DT_LENGTH, DV_DATETIME); GMTimestamp_struct_to_dt (&ts, res); DT_SET_TZ (res, DT_TZ (dt)); if (DT_TYPE_DATE == dt_type && (0 == stricmp (part, "year") || 0 == stricmp (part, "month") || 0 == stricmp (part, "day"))) DT_SET_DT_TYPE (res, dt_type); DT_AUDIT_FIELDS (dt); return res; }
caddr_t bif_string_date (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t str = bif_string_or_wide_or_null_arg (qst, args, 0, "stringdate"); caddr_t out; if (!str) sqlr_new_error ("22002", "DT007", "Nulls not allowed as parameters to stringdate"); if (DV_WIDESTRINGP (str)) { char szTemp[100]; szTemp[0] = 0; box_wide_string_as_narrow (str, szTemp, 0, QST_CHARSET (qst)); out = string_to_dt_box (szTemp); } else out = string_to_dt_box (str); DT_SET_DT_TYPE (out, DT_TYPE_DATE); return out; }
caddr_t arithm_dt_add_num (ccaddr_t box1, ccaddr_t box2, int subtraction, caddr_t *err_ret) { int dt_type = DT_DT_TYPE (box1); dtp_t dtp2 = DV_TYPE_OF (box2); boxint whole_seconds = 0; boxint nanoseconds = 0; TIMESTAMP_STRUCT ts; caddr_t res; switch (dtp2) { case DV_LONG_INT: whole_seconds = unbox (box2); break; case DV_DOUBLE_FLOAT: { double n = unbox_double (box2); double rest; whole_seconds = (n >= 0.0) ? floor(n + 0.5) : ceil(n - 0.5); rest = n - whole_seconds; if (abs(rest/n) > (3 * DBL_EPSILON)) nanoseconds = (n - whole_seconds) * 1000000000L; break; } case DV_NUMERIC: { numeric_t n = (numeric_t)box2; if (NUMERIC_STS_SUCCESS != numeric_to_int64 (n, &whole_seconds)) { err_ret[0] = srv_make_new_error ("22003", "SR087", "Wrong arguments for datetime arithmetic: decimal is out of range."); return NULL; } if (n->n_scale > 0) { char *nptr = n->n_value + n->n_len; int ctr; int mult = 1; for (ctr = 9; ctr > n->n_scale; ctr--) mult *= 10; while (ctr--) { nanoseconds += mult * nptr[ctr]; mult *= 10; } } break; } default: return NULL; } DT_AUDIT_FIELDS (dt); dt_to_GMTimestamp_struct (box1, &ts); ts_add (&ts, (subtraction ? -whole_seconds : whole_seconds), "second"); if (nanoseconds) ts_add (&ts, (subtraction ? -nanoseconds : nanoseconds), "nanosecond"); res = dk_alloc_box (DT_LENGTH, DV_DATETIME); GMTimestamp_struct_to_dt (&ts, res); DT_SET_TZ (res, DT_TZ (box1)); if ((DT_TYPE_DATE == dt_type) && (0 == (((whole_seconds * 1000000000L) + nanoseconds) % (SPERDAY * 1000000000L)))) DT_SET_DT_TYPE (res, dt_type); DT_AUDIT_FIELDS (dt); return res; }