@@ -111,14 +111,14 @@ static struct dt_d_s
dround_ddur(struct dt_d_s d, struct dt_d_s dur, bool nextp)
{
switch (dur.typ) {
unsigned int tgtd;
unsigned int tgt;
bool forw;
case DT_DAISY:
if (dur.daisydur > 0) {
tgtd = dur.daisydur;
tgt = dur.daisydur;
forw = true;
} else if (dur.daisydur < 0) {
tgtd = -dur.daisydur;
tgt = -dur.daisydur;
forw = false;
} else {
/* user is an idiot */
@@ -128,11 +128,11 @@ dround_ddur(struct dt_d_s d, struct dt_d_s dur, bool nextp)
switch (d.typ) {
unsigned int mdays;
case DT_YMD:
if ((forw && d.ymd.d < tgtd) ||
(!forw && d.ymd.d > tgtd)) {
if ((forw && d.ymd.d < tgt) ||
(!forw && d.ymd.d > tgt)) {
/* no month or year adjustment */
;
} else if (d.ymd.d == tgtd && !nextp) {
} else if (d.ymd.d == tgt && !nextp) {
/* we're ON the date already and no
* next/prev date is requested */
;
@@ -151,11 +151,11 @@ dround_ddur(struct dt_d_s d, struct dt_d_s dur, bool nextp)
}
/* get ultimo */
mdays = __get_mdays(d.ymd.y, d.ymd.m);
if (UNLIKELY(tgtd > mdays)) {
tgtd = mdays;
if (UNLIKELY(tgt > mdays)) {
tgt = mdays;
}
/* final assignment */
d.ymd.d = tgtd;
d.ymd.d = tgt;
break;
default:
break;
@@ -165,10 +165,10 @@ dround_ddur(struct dt_d_s d, struct dt_d_s dur, bool nextp)
case DT_BIZSI:
/* bizsis only work on bizsidurs atm */
if (dur.bizsidur > 0) {
tgtd = dur.bizsidur;
tgt = dur.bizsidur;
forw = true;
} else if (dur.bizsidur < 0) {
tgtd = -dur.bizsidur;
tgt = -dur.bizsidur;
forw = false;
} else {
/* user is an idiot */
@@ -178,11 +178,11 @@ dround_ddur(struct dt_d_s d, struct dt_d_s dur, bool nextp)
switch (d.typ) {
unsigned int bdays;
case DT_BIZDA:
if ((forw && d.bizda.bd < tgtd) ||
(!forw && d.bizda.bd > tgtd)) {
if ((forw && d.bizda.bd < tgt) ||
(!forw && d.bizda.bd > tgt)) {
/* no month or year adjustment */
;
} else if (d.bizda.bd == tgtd && !nextp) {
} else if (d.bizda.bd == tgt && !nextp) {
/* we're ON the date already and no
* next/prev date is requested */
;
@@ -201,20 +201,86 @@ dround_ddur(struct dt_d_s d, struct dt_d_s dur, bool nextp)
}
/* get ultimo */
bdays = __get_bdays(d.bizda.y, d.bizda.m);
if (UNLIKELY(tgtd > bdays)) {
tgtd = bdays;
if (UNLIKELY(tgt > bdays)) {
tgt = bdays;
}
/* final assignment */
d.bizda.bd = tgtd;
d.bizda.bd = tgt;
break;
default:
break;
}
break;

/* non-daisys are not supported atm */
case DT_YMCW:
case DT_YMD:
switch (d.typ) {
unsigned int mdays;
case DT_YMD:
forw = !dur.neg;
tgt = dur.ymd.m;

if ((forw && d.ymd.m < tgt) ||
(!forw && d.ymd.m > tgt)) {
/* no year adjustment */
;
} else if (d.ymd.m == tgt && !nextp) {
/* we're IN the month already and no
* next/prev date is requested */
;
} else if (forw) {
/* years don't wrap around */
d.ymd.y++;
} else {
/* years don't wrap around */
d.ymd.y--;
}
/* final assignment */
d.ymd.m = tgt;
/* fixup ultimo mismatches */
mdays = __get_mdays(d.ymd.y, d.ymd.m);
if (UNLIKELY(d.ymd.d > mdays)) {
d.ymd.d = mdays;
}
break;
default:
break;
}
break;

case DT_YMCW: {
struct dt_d_s tmp;
unsigned int wday;
signed int diff;

forw = !dur.neg;
tgt = dur.ymcw.w;

tmp = dt_conv(DT_DAISY, d);
wday = dt_get_wday(tmp);
diff = (signed)tgt - (signed)wday;


if ((forw && wday < tgt) ||
(!forw && wday > tgt)) {
/* nothing to do */
;
} else if (wday == tgt && !nextp) {
/* we're on WDAY already, do fuckall */
;
} else if (forw) {
/* week wrap */
diff += 7;
} else {
/* week wrap */
diff -= 7;
}

/* final assignment */
tmp.daisy += diff;
d = dt_conv(d.typ, tmp);
break;
}

case DT_MD:
default:
break;
@@ -264,24 +330,47 @@ dt_io_strpdtrnd(struct __strpdtdur_st_s *st, const char *str)
const char *sp = NULL;
struct strpd_s d;
struct dt_spec_s s;
struct dt_dt_s payload = dt_dt_initialiser();
bool negp = false;

if (dt_io_strpdtdur(st, str) >= 0) {
return 0;
}

/* check if there's a sign + or - */
if (*str == '-') {
negp = true;
str++;
} else if (*str == '+') {
str++;
}

/* try weekdays, set up s */
s.spfl = DT_SPFL_S_WDAY;
s.abbr = DT_SPMOD_NORM;
if (__strpd_card(&d, str, s, (char**)&sp) >= 0) {
dt_make_d_only(&payload, DT_DUNK);
payload.d = dt_make_ymcw(0, 0, 0, d.w);
goto out;
}

/* try months, set up s */
s.spfl = DT_SPFL_S_MON;
s.abbr = DT_SPMOD_NORM;
if (__strpd_card(&d, str, s, (char**)&sp) >= 0) {
dt_make_d_only(&payload, DT_DUNK);
payload.d = dt_make_ymd(0, d.m, 0);
goto out;
}

/* bugger */
st->istr = str;
return -1;
out:
st->sign = 0;
st->cont = NULL;
return 0;
payload.neg = negp;
return __add_dur(st, payload);
}


@@ -736,7 +736,6 @@ struct __strpdtdur_st_s {
int sign;
const char *istr;
const char *cont;
struct dt_dt_s curr;
size_t ndurs;
struct dt_dt_s *durs;
};
@@ -756,6 +755,24 @@ __strpdtdur_free(struct __strpdtdur_st_s *st)
return;
}

static int
__add_dur(struct __strpdtdur_st_s *st, struct dt_dt_s dur)
{
if (dt_unk_p(dur)) {
return -1;
}
if (st->durs == NULL) {
st->durs = calloc(16, sizeof(*st->durs));
} else if ((st->ndurs % 16) == 0) {
st->durs = realloc(
st->durs,
(16 + st->ndurs) * sizeof(*st->durs));
memset(st->durs + st->ndurs, 0, 16 * sizeof(*st->durs));
}
st->durs[st->ndurs++] = dur;
return 0;
}

static int __attribute__((unused))
dt_io_strpdtdur(struct __strpdtdur_st_s *st, const char *str)
{
@@ -816,24 +833,13 @@ dt_io_strpdtdur(struct __strpdtdur_st_s *st, const char *str)
}

/* try reading the stuff with our strpdur() */
st->curr = dt_strpdtdur(sp, (char**)&ep);
if (!dt_unk_p(st->curr)) {
if (st->durs == NULL) {
st->durs = calloc(16, sizeof(*st->durs));
} else if ((st->ndurs % 16) == 0) {
st->durs = realloc(
st->durs,
(16 + st->ndurs) * sizeof(*st->durs));
memset(st->durs + st->ndurs, 0, 16 * sizeof(*st->durs));
}
if ((st->sign == 1 && dt_dtdur_neg_p(st->curr)) ||
(st->sign == -1 && !dt_dtdur_neg_p(st->curr))) {
st->durs[st->ndurs++] = dt_neg_dtdur(st->curr);
} else {
st->durs[st->ndurs++] = st->curr;
{
struct dt_dt_s d = dt_strpdtdur(sp, (char**)&ep);
if ((st->sign == 1 && dt_dtdur_neg_p(d)) ||
(st->sign == -1 && !dt_dtdur_neg_p(d))) {
d = dt_neg_dtdur(d);
}
} else {
res = -1;
res = __add_dur(st, d);
}
out:
if (((st->cont = ep) && *ep == '\0') || (sp == ep)) {
@@ -139,6 +139,22 @@ dt_tests += dround.1.dt
dt_tests += dround.2.dt
dt_tests += dround.3.dt
dt_tests += dround.4.dt
dt_tests += dround.5.dt
dt_tests += dround.6.dt
dt_tests += dround.7.dt
dt_tests += dround.8.dt
dt_tests += dround.9.dt
dt_tests += dround.10.dt
dt_tests += dround.11.dt
dt_tests += dround.12.dt
dt_tests += dround.13.dt
dt_tests += dround.14.dt
dt_tests += dround.15.dt
dt_tests += dround.16.dt
dt_tests += dround.17.dt
dt_tests += dround.18.dt
dt_tests += dround.19.dt
dt_tests += dround.20.dt


dt_tests += tseq.1.dt
@@ -286,6 +302,19 @@ dt_tests += dtdiff.10.dt
dt_tests += dtdiff.11.dt
dt_tests += dtdiff.12.dt

dt_tests += dtround.1.dt
dt_tests += dtround.2.dt
dt_tests += dtround.3.dt
dt_tests += dtround.4.dt
dt_tests += dtround.5.dt
dt_tests += dtround.6.dt
dt_tests += dtround.7.dt
dt_tests += dtround.8.dt
dt_tests += dtround.9.dt
dt_tests += dtround.10.dt
dt_tests += dtround.11.dt
dt_tests += dtround.12.dt

dt_tests += strptime.1.dt
dt_tests += strptime.2.dt

@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-01 -- -Thu"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-02-23
EOF

## dround.10.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-01 -- -Sat"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-02-25
EOF

## dround.11.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-01 -- -Sat"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-02-25
EOF

## dround.12.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-01 Mar"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-01
EOF

## dround.13.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-01 Mar"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2013-03-01
EOF

## dround.14.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-01 Sep"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-09-01
EOF

## dround.15.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-01 Sep"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-09-01
EOF

## dround.16.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04 -- -Mar"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04
EOF

## dround.17.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-04 -- -Mar"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2011-03-04
EOF

## dround.18.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04 -- -Sep"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2011-09-04
EOF

## dround.19.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-04 -- -Sep"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2011-09-04
EOF

## dround.20.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-01 Sat"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-03
EOF

## dround.5.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-01 Thu"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-01
EOF

## dround.6.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-01 Thu"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-08
EOF

## dround.7.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 2012-03-01 Sat"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-03
EOF

## dround.8.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-01 -- -Thu"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-01
EOF

## dround.9.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:04:11 1s"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:04:11
EOF

## dtround.1.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:03:11 1h"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T13:00:00
EOF

## dtround.10.dt ends here
@@ -0,0 +1,28 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="5m"

## STDIN
stdin=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdin}" <<EOF
2012-03-04T11:01:01
2012-03-04T11:01:02
2012-03-04T11:05:01
2012-03-04T11:06:01
2012-03-04T11:12:00
2012-03-04T11:15:00
EOF

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T11:05:00
2012-03-04T11:05:00
2012-03-04T11:10:00
2012-03-04T11:10:00
2012-03-04T11:15:00
2012-03-04T11:15:00
EOF

## dtround.11.dt ends here
@@ -0,0 +1,28 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="-n 5m"

## STDIN
stdin=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdin}" <<EOF
2012-03-04T11:01:01
2012-03-04T11:01:02
2012-03-04T11:05:01
2012-03-04T11:06:01
2012-03-04T11:12:00
2012-03-04T11:15:00
EOF

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T11:05:00
2012-03-04T11:05:00
2012-03-04T11:10:00
2012-03-04T11:10:00
2012-03-04T11:15:00
2012-03-04T11:20:00
EOF

## dtround.12.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:04:11 5s"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:04:15
EOF

## dtround.2.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:04:11 10s"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:04:20
EOF

## dtround.3.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:04:11 30s"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:04:30
EOF

## dtround.4.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:03:11 1m"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:04:00
EOF

## dtround.5.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:03:11 5m"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:05:00
EOF

## dtround.6.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:03:11 10m"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:10:00
EOF

## dtround.7.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:03:11 15m"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:15:00
EOF

## dtround.8.dt ends here
@@ -0,0 +1,14 @@
## -*- shell-script -*-

TOOL=dround
CMDLINE="2012-03-04T12:03:11 30m"

## STDIN

## STDOUT
stdout=$(mktemp "/tmp/tmp.XXXXXXXXXX")
cat > "${stdout}" <<EOF
2012-03-04T12:30:00
EOF

## dtround.9.dt ends here