static struct dt_dt_s dt_round(struct dt_dt_s d, struct dt_dtdur_s dur, bool nextp) { switch (dur.durtyp) { default: /* all the date durs */ break; case DT_DURH: case DT_DURM: case DT_DURS: case DT_DURNANO: if (!dur.cocl) { d.t = tround_tdur(d.t, dur, nextp); } else { d.t = tround_tdur_cocl(d.t, dur, nextp); } break; } /* check carry */ if (UNLIKELY(d.t.carry)) { /* we need to add a day */ struct dt_ddur_s one_day = dt_make_ddur(DT_DURD, d.t.carry); d.t.carry = 0; d.d = dt_dadd(d.d, one_day); } { unsigned int sw = d.sandwich; d.d = dround_ddur(d.d, dur.d, nextp); d.sandwich = (uint8_t)sw; } return d; }
static __attribute__((const, pure)) struct dt_ddur_s __daisy_diff(dt_daisy_t d1, dt_daisy_t d2) { /* compute d2 - d1 */ int32_t diff = d2 - d1; return dt_make_ddur(DT_DURD, diff); }
static struct dt_ddur_s __ymcw_diff(dt_ymcw_t d1, dt_ymcw_t d2) { /* compute d2 - d1 entirely in terms of ymd */ struct dt_ddur_s res = dt_make_ddur(DT_DURYMCW, 0); signed int tgtd; signed int tgtm; dt_dow_t wd01, wd02; if (__ymcw_cmp(d1, d2) > 0) { dt_ymcw_t tmp = d1; d1 = d2; d2 = tmp; res.neg = 1; } wd01 = __get_m01_wday(d1.y, d1.m); if (d2.y != d1.y || d2.m != d1.m) { wd02 = __get_m01_wday(d2.y, d2.m); } else { wd02 = wd01; } /* first compute the difference in months Y2-M2-01 - Y1-M1-01 */ tgtm = GREG_MONTHS_P_YEAR * (d2.y - d1.y) + (d2.m - d1.m); /* using the firsts of the month WD01, represent d1 and d2 as * the C-th WD01 plus OFF */ { unsigned int off1; unsigned int off2; off1 = __uimod(d1.w - wd01, GREG_DAYS_P_WEEK); off2 = __uimod(d2.w - wd02, GREG_DAYS_P_WEEK); tgtd = off2 - off1 + GREG_DAYS_P_WEEK * (d2.c - d1.c); } /* fixups */ if (tgtd < (signed int)GREG_DAYS_P_WEEK && tgtm > 0) { /* if tgtm is 0 it remains 0 and tgtd remains negative */ /* get the target month's mdays */ unsigned int d2m = d2.m; unsigned int d2y = d2.y; if (--d2m < 1) { d2m = GREG_MONTHS_P_YEAR; d2y--; } tgtd += __get_mdays(d2y, d2m); tgtm--; } /* fill in the results */ res.ymcw.y = tgtm / GREG_MONTHS_P_YEAR; res.ymcw.m = tgtm % GREG_MONTHS_P_YEAR; res.ymcw.c = tgtd / GREG_DAYS_P_WEEK; res.ymcw.w = tgtd % GREG_DAYS_P_WEEK; return res; }
int main(int argc, char *argv[]) { static struct dt_dtdur_s ite_p1; yuck_t argi[1U]; struct dt_dt_s tmp; char **ifmt; size_t nifmt; char *ofmt; dt_dttyp_t tgttyp; int rc = 0; struct dseq_clo_s clo = { .ite = &ite_p1, .nite = 1, .altite = NULL, .naltite = 0, .ss = 0, .dir = 0, .flags = 0, }; if (yuck_parse(argi, argc, argv)) { rc = 1; goto out; } /* assign ofmt/ifmt */ ofmt = argi->format_arg; if (argi->backslash_escapes_flag) { dt_io_unescape(ofmt); } nifmt = argi->input_format_nargs; ifmt = argi->input_format_args; if (argi->from_locale_arg) { setilocale(argi->from_locale_arg); } if (argi->locale_arg) { setflocale(argi->locale_arg); } if (argi->base_arg) { struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL); dt_set_base(base); } for (size_t i = 0; i < argi->skip_nargs; i++) { clo.ss = set_skip(clo.ss, argi->skip_args[i]); } if (argi->alt_inc_arg) { struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); do { if (dt_io_strpdtdur(&st, argi->alt_inc_arg) < 0) { if (!argi->quiet_flag) { error("Error: \ cannot parse duration string `%s'", argi->alt_inc_arg); } rc = 1; goto out; } } while (__strpdtdur_more_p(&st)); /* assign values */ clo.altite = st.durs; clo.naltite = st.ndurs; } switch (argi->nargs) { struct dt_dt_s fst, lst; default: yuck_auto_help(argi); rc = 1; goto out; case 2: lst = dt_io_strpdt(argi->args[1U], ifmt, nifmt, NULL); if (dt_unk_p(lst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[1U]); } rc = 1; goto out; } else if (UNLIKELY(lst.fix) && !argi->quiet_flag) { rc = 2; } /* fallthrough */ case 1: fst = dt_io_strpdt(argi->args[0U], ifmt, nifmt, NULL); if (dt_unk_p(fst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[0U]); } rc = 1; goto out; } else if (UNLIKELY(fst.fix) && !argi->quiet_flag) { rc = 2; } /* check the input arguments and do the sane thing now * if it's all dates, use DURD iterator * if it's all times, use DURS/DURM/DURH iterators * if one of them is a dt, promote the other */ if (dt_sandwich_only_d_p(fst)) { /* emulates old dseq(1) */ if (argi->nargs == 1U) { lst.d = dt_date(fst.d.typ); dt_make_d_only(&lst, fst.d.typ); } clo.ite->d = dt_make_ddur(DT_DURD, 1); } else if (dt_sandwich_only_t_p(fst)) { /* emulates old tseq(1) */ if (argi->nargs == 1U) { lst.t = dt_time(); dt_make_t_only(&lst, DT_HMS); } } else if (dt_sandwich_p(fst)) { if (argi->nargs == 1U) { lst = dt_datetime(fst.typ); dt_make_sandwich(&lst, fst.d.typ, DT_HMS); } clo.ite->d = dt_make_ddur(DT_DURD, 1); } else { error("\ don't know how to handle single argument case"); rc = 1; goto out; } goto make_compat; case 3: { struct __strpdtdur_st_s st = __strpdtdur_st_initialiser(); /* get lower bound */ fst = dt_io_strpdt(argi->args[0U], ifmt, nifmt, NULL); if (dt_unk_p(fst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[0U]); } rc = 1; goto out; } else if (UNLIKELY(fst.fix) && !argi->quiet_flag) { rc = 2; } /* get increment */ do { if (dt_io_strpdtdur(&st, argi->args[1U]) < 0) { error("Error: \ cannot parse duration string `%s'", argi->args[1U]); rc = 1; goto out; } } while (__strpdtdur_more_p(&st)); /* assign values */ clo.ite = st.durs; clo.nite = st.ndurs; clo.flags |= CLO_FL_FREE_ITE; /* get upper bound */ lst = dt_io_strpdt(argi->args[2U], ifmt, nifmt, NULL); if (dt_unk_p(lst)) { if (!argi->quiet_flag) { dt_io_warn_strpdt(argi->args[2U]); } rc = 1; goto out; } else if (UNLIKELY(lst.fix) && !argi->quiet_flag) { rc = 2; } goto make_compat; } make_compat: if (LIKELY(fst.typ == lst.typ)) { clo.fst = fst; clo.lst = lst; } else { clo.fst = fst; clo.lst = dt_dtconv(fst.typ, lst); } break; } /* promote the args maybe */ if ((dt_sandwich_only_d_p(clo.fst) && dt_sandwich_only_t_p(clo.lst)) || (dt_sandwich_only_t_p(clo.fst) && dt_sandwich_only_d_p(clo.lst))) { error("\ cannot mix dates and times as arguments"); rc = 1; goto out; } else if (dt_sandwich_only_d_p(clo.fst) && dt_sandwich_p(clo.lst)) {