Exemplo n.º 1
0
static int
dt_add_t(void)
{
	static const char str[] = "2012-03-28T23:12:01";
	struct dt_dt_s d;
	struct dt_dt_s dur;
	int res = 0;

	fprintf(stderr, "testing %s +1h ...\n", str);
	d = dt_strpdt(str, NULL, NULL);

	/* we lack some lovely ctors for this */
	dur.d = dt_d_initialiser();
	dt_make_t_only(&dur, DT_TUNK);
	dur.dur = 1;
	dur.neg = 0;
	dur.t.dur = 1;
	dur.t.neg = 0;
	dur.t.sdur = 3600;

	/* the actual addition */
	d = dt_dtadd(d, dur);

	CHECK(d.d.typ != DT_YMD,
	      "  DATE TYPE DIFFERS %u ... should be %u\n",
	      (unsigned int)d.d.typ,
	      (unsigned int)DT_YMD);
	CHECK(d.t.typ != DT_HMS,
	      "  TIME TYPE DIFFERS %u ... should be %u\n",
	      (unsigned int)d.t.typ,
	      (unsigned int)DT_HMS);
	CHECK(d.dur, "  DURATION BIT SET\n");
	CHECK(d.neg, "  NEGATED BIT SET\n");
	CHECK(d.t.dur, "  TIME DURATION BIT SET\n");
	CHECK(d.t.neg, "  TIME NEGATED BIT SET\n");

	CHECK_EQ((unsigned int)d.d.ymd.y, 2012U,
		 "  YEAR %u ... should be %u\n");
	CHECK_EQ((unsigned int)d.d.ymd.m, 3U,
		 "  MONTH %u ... should be %u\n");
	CHECK_EQ((unsigned int)d.d.ymd.d, 29U,
		 "  DAY %u ... should be %u\n");

	CHECK_EQ((unsigned int)d.t.hms.h, 00U,
		 "  HOUR %u ... should be %u\n");
	CHECK_EQ((unsigned int)d.t.hms.m, 12U,
		 "  MINUTE %u ... should be %u\n");
	CHECK_EQ((unsigned int)d.t.hms.s, 01U,
		 "  SECOND %u ... should be %u\n");

	/* make sure the padding leaves no garbage */
	CHECK_RES(res, d.d.ymd.u & ~0x1fffff,
		  "  PADDING NOT NAUGHT %x\n",
		  (unsigned int)(d.d.ymd.u & ~0x1fffff));
	CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff,
		  "  TIME PADDING NOT NAUGHT %x\n",
		  (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff));
	return res;
}
Exemplo n.º 2
0
static int
add_t_only(void)
{
	static const char str[] = "12:34:56";
	struct dt_dt_s d;
	struct dt_dt_s dur;
	int res = 0;

	/* 2012-03-28 (using no format) */
	fprintf(stderr, "testing %s +1h ...\n", str);
	d = dt_strpdt(str, NULL, NULL);

	/* we lack some lovely ctors for this */
	dur.d = dt_d_initialiser();
	dt_make_t_only(&dur, DT_TUNK);
	dur.dur = 1;
	dur.neg = 0;
	dur.t.dur = 1;
	dur.t.neg = 0;
	dur.t.sdur = 3600;

	/* the actual addition */
	d = dt_dtadd(d, dur);

	CHECK(d.typ != DT_SANDWICH_UNK,
	      "  TYPE DIFFERS %u ... should be %u\n",
	      (unsigned int)d.typ,
	      (unsigned int)DT_SANDWICH_UNK);
	CHECK(d.t.typ != DT_HMS,
	      "  TYPE DIFFERS %u ... should be %u\n",
	      (unsigned int)d.t.typ,
	      (unsigned int)DT_HMS);
	CHECK(d.d.u,
	      "  DATE COMPONENT NOT NAUGHT %" PRIu64 "\n",
	      (uint64_t)d.d.u);
	CHECK(d.dur, "  DURATION BIT SET\n");
	CHECK(d.neg, "  NEGATED BIT SET\n");
	CHECK(d.t.dur, "  TIME DURATION BIT SET\n");
	CHECK(d.t.neg, "  TIME NEGATED BIT SET\n");

	CHECK_EQ((unsigned int)d.t.hms.h, 13U,
		 "  HOUR %u ... should be %u\n");
	CHECK_EQ((unsigned int)d.t.hms.m, 34U,
		 "  MINUTE %u ... should be %u\n");
	CHECK_EQ((unsigned int)d.t.hms.s, 56U,
		 "  SECOND %u ... should be %u\n");
	/* make sure the padding leaves no garbage */
	CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff,
		  "  PADDING NOT NAUGHT %x\n",
		  (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff));
	return res;
}
Exemplo n.º 3
0
static struct dt_dt_s
__fixup_zdiff(struct dt_dt_s dt, int32_t zdiff)
{
	/* apply time zone difference */
	struct dt_dt_s zd = dt_dt_initialiser();

	dt_make_t_only(&zd, DT_HMS);
	zd.t.dur = 1;
	zd.t.sdur = -zdiff;
	/* reuse dt for result */
	dt = dt_dtadd(dt, zd);
	dt.znfxd = 1;
	return dt;
}
Exemplo n.º 4
0
DEFUN struct dt_dt_s
__strpdt_std(const char *str, char **ep)
{
/* code dupe, see __strpd_std() */
	struct dt_dt_s res = dt_dt_initialiser();
	struct strpdt_s d = strpdt_initialiser();
	const char *sp;

	if ((sp = str) == NULL) {
		goto out;
	}
	/* check for epoch notation */
	if (*sp == '@') {
		/* yay, epoch */
		const char *tmp;
		d.i = strtoi(++sp, &tmp);
		if (UNLIKELY(d.i == -1 && sp == tmp)) {
			sp--;
		} else {
			/* let's make a DT_SEXY */
			res.typ = DT_SEXY;
			res.sxepoch = d.i;
		}
		goto out;
	}
	/* read the year */
	if ((d.sd.y = strtoi_lim(sp, &sp, DT_MIN_YEAR, DT_MAX_YEAR)) < 0 ||
	    *sp++ != '-') {
		sp = str;
		goto try_time;
	}
	/* check for ywd dates */
	if (UNLIKELY(*sp == 'W')) {
		/* brilliant */
		if ((sp++, d.sd.c = strtoi_lim(sp, &sp, 0, 53)) < 0 ||
		    *sp++ != '-') {
			goto try_time;
		}
		d.sd.flags.c_wcnt_p = 1;
		d.sd.flags.wk_cnt = YWD_ISOWK_CNT;
		goto dow;
	}
	/* read the month */
	if ((d.sd.m = strtoi_lim(sp, &sp, 0, 12)) < 0 ||
	    *sp++ != '-') {
		sp = str;
		goto out;
	}
	/* read the day or the count */
	if ((d.sd.d = strtoi_lim(sp, &sp, 0, 31)) < 0) {
		/* didn't work, f**k off */
		sp = str;
		goto out;
	}
	/* check the date type */
	switch (*sp) {
	case '-':
		/* it is a YMCW date */
		if ((d.sd.c = d.sd.d) > 5) {
			/* nope, it was bollocks */
			break;
		}
		d.sd.d = 0;
	dow:
		if ((d.sd.w = strtoi_lim(++sp, &sp, 0, 7)) < 0) {
			/* didn't work, f**k off */
			sp = str;
			goto out;
		}
		/* fix up d.sd.w right away */
		d.sd.w = d.sd.w ?: DT_SUNDAY;
		break;
	case 'B':
		/* it's a bizda/YMDU before ultimo date */
		d.sd.flags.ab = BIZDA_BEFORE;
	case 'b':
		/* it's a bizda/YMDU after ultimo date */
		d.sd.flags.bizda = 1;
		d.sd.b = d.sd.d;
		d.sd.d = 0;
		sp++;
		break;
	default:
		/* we don't care */
		break;
	}
	/* guess what we're doing */
	if ((res.d = __guess_dtyp(d.sd)).typ == DT_DUNK) {
		/* not much use parsing on */
		goto out;
	}
	/* check for the d/t separator */
	switch (*sp) {
	case 'T':
	case ' ':
	case '\t':
		/* could be a time, could be something, else
		 * make sure we leave a mark */
		str = sp++;
		break;
	default:
		/* should be a no-op */
		dt_make_d_only(&res, res.d.typ);
		goto out;
	}
try_time:
	/* and now parse the time */
	if ((d.st.h = strtoi_lim(sp, &sp, 0, 23)) < 0) {
		sp = str;
		goto out;
	} else if (*sp != ':') {
		goto eval_time;
	} else if ((d.st.m = strtoi_lim(++sp, &sp, 0, 59)) < 0) {
		d.st.m = 0;
		goto eval_time;
	} else if (*sp != ':') {
		goto eval_time;
	} else if ((d.st.s = strtoi_lim(++sp, &sp, 0, 60)) < 0) {
		d.st.s = 0;
	} else if (*sp != '.') {
		goto eval_time;
	} else if ((d.st.ns = strtoi_lim(++sp, &sp, 0, 999999999)) < 0) {
		d.st.ns = 0;
		goto eval_time;
	}
eval_time:
	res.t.hms.h = d.st.h;
	res.t.hms.m = d.st.m;
	res.t.hms.s = d.st.s;
	if (res.d.typ > DT_DUNK) {
		const char *tp;
		dt_make_sandwich(&res, res.d.typ, DT_HMS);
		/* check for the zone stuff */
		if ((d.zdiff = try_zone(sp, &tp))) {
			res = __fixup_zdiff(res, d.zdiff);
		} else if (tp > sp) {
			res.znfxd = 1U;
		}
		sp = tp;
	} else {
		dt_make_t_only(&res, DT_HMS);
	}
out:
	/* res.typ coincides with DT_SANDWICH_D_ONLY() if we jumped here */
	if (ep != NULL) {
		*ep = (char*)sp;
	}
	return res;
}
Exemplo n.º 5
0
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)) {