Permalink
Browse files

Merge branch 'core/date' into next

* core/date:
  doc, minor, move format specs to Calendars chapter
  doc, document week counts, %U %V and %W
  minor, implement week counts (in all their colours)
  minor, introduce all week-count conventions and lift struct dt_spec_s to token.h
  minor, follow-up, cope with new counter symbols everywhere, {D,W}CNT_*
  minor, refactor counting tokens, DCNT_{WEEK,MON,YEAR}, WCNT_{MON,YEAR}
  • Loading branch information...
hroptatyr committed Apr 17, 2012
2 parents 23df302 + 4b8d2bb commit dd3fd48f419d5231eb08deb925f2b2728cb95a6a
Showing with 259 additions and 128 deletions.
  1. +2 −2 info/dateutils.texi
  2. +3 −0 info/format.texi
  3. +108 −21 lib/date-core.c
  4. +15 −12 lib/dt-core.c
  5. +24 −45 lib/token.c
  6. +56 −10 lib/token.h
  7. +5 −4 src/date-io.h
  8. +8 −7 src/ddiff.c
  9. +12 −10 src/dexpr-parser.y
  10. +21 −13 src/dexpr.c
  11. +5 −4 src/dt-io.h
View
@@ -90,8 +90,6 @@ to a given date. Besides, most of the time those billions of dates come
from external sources and have to be brought into shape before or whilst
importing them into an integrated system.
-@include format.texi
-
@node Calendars
@chapter Calendars
@@ -174,6 +172,8 @@ The canonical input and output format is @code{%Y-%m-%db}, where
ultimo. Similarly, @code{%Y-%m-%dB} stands for the business days until
this month's ultimo.
+@include format.texi
+
@include strptime.texi
@include dconv.texi
View
@@ -21,7 +21,10 @@ Date specs:
%m The month in the current calendar (range 00 to 19)
%Q The quarter of the year (range Q1 to Q4)
%q The number of the quarter (range 01 to 04)
+ %U The week count, first day of week is Sun (range 00 to 53)
+ %V The ISO week count, first day of week is Mon (range 01 to 53)
%w The weekday as number (range 00 to 06, Sunday being 00)
+ %W The week count, first day of week is Mon (range 00 to 53)
%y The year without a century (range 00 to 99)
%Y The year including the century
View
@@ -713,6 +713,71 @@ __ymcw_get_mday(dt_ymcw_t that)
return res;
}
+static int
+__ymd_get_wcnt(dt_ymd_t d, int wdays_from)
+{
+ int yd = __ymd_get_yday(d);
+ int y01 = (int)__get_jan01_wday(d.y);
+ int wk;
+
+ /* yd of the FIRST week of the year */
+ if ((wk = 8 - y01 + wdays_from) > 7) {
+ wk -= 7;
+ }
+ /* and now express yd as 7k + n relative to jan01 */
+ return (yd - wk + 7) / 7;
+}
+
+static int
+__ymd_get_wcnt_iso(dt_ymd_t d)
+{
+/* like __ymd_get_wcnt() but for iso week conventions
+ * the week with the first thursday is the first week,
+ * so a year starting on S is the first week,
+ * a year starting on M is the first week
+ * a year starting on T ... */
+ /* iso weeks always start on Mon */
+ static const int_fast8_t iso[] = {2, 1, 0, -1, -2, 4, 3};
+ int yd = __ymd_get_yday(d);
+ unsigned int y = d.y;
+ int y01 = (int)__get_jan01_wday(y);
+ int wk;
+
+ /* express yd as 7k + n relative to jan01 */
+ if (UNLIKELY((wk = (yd - iso[y01] + 7) / 7) < 1)) {
+ /* get last years y01
+ * which is basically y01 - (365|366 % 7) */
+ if (LIKELY(!__leapp(--y))) {
+ /* -= 1 */
+ y01 += 6;
+ yd += 365;
+ } else {
+ /* -= 2 */
+ y01 += 5;
+ yd += 366;
+ }
+ if (y01 >= DT_MIRACLEDAY) {
+ y01 -= 7;
+ }
+ /* same computation now */
+ wk = (yd - iso[y01] + 7) / 7;
+ }
+ if (UNLIKELY(wk == 53)) {
+ /* check next year's y01 */
+ if (LIKELY(!__leapp(y))) {
+ y01 += 1;
+ } else {
+ /* -= 2 */
+ y01 += 2;
+ }
+ if (!(y01 == DT_FRIDAY || y01 == DT_SATURDAY)) {
+ /* 53rd week is no more */
+ wk = 1;
+ }
+ }
+ return wk;
+}
+
static int
__ymd_get_bday(dt_ymd_t that, dt_bizda_param_t bp)
{
@@ -2116,7 +2181,7 @@ __strpd_card(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep)
d->m = strtoui_lim(sp, &sp, 0, GREG_MONTHS_P_YEAR);
res = 0 - (d->m == -1U);
break;
- case DT_SPFL_N_MDAY:
+ case DT_SPFL_N_DCNT_MON:
/* ymd mode? */
if (LIKELY(!s.bizda)) {
d->d = strtoui_lim(sp, &sp, 0, 31);
@@ -2126,12 +2191,12 @@ __strpd_card(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep)
res = 0 - (d->b == -1U);
}
break;
- case DT_SPFL_N_CNT_WEEK:
+ case DT_SPFL_N_DCNT_WEEK:
/* ymcw mode? */
d->w = strtoui_lim(sp, &sp, 0, GREG_DAYS_P_WEEK);
res = 0 - (d->w == -1U);
break;
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_WCNT_MON:
/* ymcw mode? */
d->c = strtoui_lim(sp, &sp, 0, 5);
res = 0 - (d->c == -1U);
@@ -2223,10 +2288,14 @@ __strpd_card(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep)
res = 0;
}
break;
- case DT_SPFL_N_CNT_YEAR:
- /* was %C and %j, cannot be used at the moment */
+ case DT_SPFL_N_DCNT_YEAR:
+ /* was %D and %j, cannot be used at the moment */
(void)strtoui_lim(sp, &sp, 1, 366);
break;
+ case DT_SPFL_N_WCNT_YEAR:
+ /* was %C, cannot be used at the moment */
+ (void)strtoui_lim(sp, &sp, 0, 53);
+ break;
}
/* assign end pointer */
if (ep) {
@@ -2263,11 +2332,11 @@ __strpd_rom(struct strpd_s *d, const char *sp, struct dt_spec_s s, char **ep)
d->m = romstrtoui_lim(sp, &sp, 0, GREG_MONTHS_P_YEAR);
res = 0 - (d->m == -1U);
break;
- case DT_SPFL_N_MDAY:
+ case DT_SPFL_N_DCNT_MON:
d->d = romstrtoui_lim(sp, &sp, 0, 31);
res = 0 - (d->d == -1U);
break;
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_WCNT_MON:
d->c = romstrtoui_lim(sp, &sp, 0, 5);
res = 0 - (d->c == -1U);
break;
@@ -2310,7 +2379,7 @@ __strfd_card(
case DT_SPFL_N_MON:
res = ui32tostr(buf, bsz, d->m, 2);
break;
- case DT_SPFL_N_MDAY:
+ case DT_SPFL_N_DCNT_MON:
/* ymd mode check? */
if (LIKELY(!s.bizda)) {
d->d = d->d ?: (unsigned int)dt_get_mday(that);
@@ -2321,12 +2390,12 @@ __strfd_card(
res = ui32tostr(buf, bsz, bd, 2);
}
break;
- case DT_SPFL_N_CNT_WEEK:
+ case DT_SPFL_N_DCNT_WEEK:
/* ymcw mode check */
d->w = d->w ?: dt_get_wday(that);
res = ui32tostr(buf, bsz, d->w, 2);
break;
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_WCNT_MON:
/* ymcw mode check? */
d->c = d->c ?: (unsigned int)dt_get_count(that);
res = ui32tostr(buf, bsz, d->c, 2);
@@ -2401,7 +2470,7 @@ __strfd_card(
buf[res++] = '\n';
break;
- case DT_SPFL_N_CNT_YEAR:
+ case DT_SPFL_N_DCNT_YEAR:
if (that.typ == DT_YMD || that.typ == DT_BIZDA) {
/* %j */
int yd;
@@ -2418,12 +2487,29 @@ __strfd_card(
buf[res++] = '0';
buf[res++] = '0';
}
- } else if (that.typ == DT_YMCW) {
- /* %C */
- int yd = __ymcw_get_yday(that.ymcw);
- res = ui32tostr(buf, bsz, yd, 2);
}
break;
+ case DT_SPFL_N_WCNT_YEAR: {
+ int yw;
+ /* %C/%W week count */
+ switch (that.typ) {
+ case DT_YMD:
+ if (s.cnt_weeks_iso) {
+ yw = __ymd_get_wcnt_iso(that.ymd);
+ } else {
+ yw = __ymd_get_wcnt(that.ymd, s.cnt_wdays_from);
+ }
+ break;
+ case DT_YMCW:
+ yw = __ymcw_get_yday(that.ymcw);
+ break;
+ default:
+ yw = 0;
+ break;
+ }
+ res = ui32tostr(buf, bsz, yw, 2);
+ break;
+ }
}
return res;
}
@@ -2456,10 +2542,10 @@ __strfd_rom(
case DT_SPFL_N_MON:
res = ui32tostrrom(buf, bsz, d->m);
break;
- case DT_SPFL_N_MDAY:
+ case DT_SPFL_N_DCNT_MON:
res = ui32tostrrom(buf, bsz, d->d);
break;
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_WCNT_MON:
d->c = d->c ?: (unsigned int)dt_get_count(that);
res = ui32tostrrom(buf, bsz, d->c);
break;
@@ -2479,7 +2565,7 @@ __strfd_dur(
case DT_SPFL_UNK:
break;
case DT_SPFL_N_DSTD:
- case DT_SPFL_N_MDAY:
+ case DT_SPFL_N_DCNT_MON:
res = snprintf(buf, bsz, "%d", d->sd);
break;
case DT_SPFL_N_YEAR:
@@ -2494,7 +2580,7 @@ __strfd_dur(
case DT_SPFL_N_MON:
res = snprintf(buf, bsz, "%u", d->m);
break;
- case DT_SPFL_N_CNT_WEEK:
+ case DT_SPFL_N_DCNT_WEEK:
if (!d->w) {
/* hack hack hack
* we'll think about the consequences later */
@@ -2503,14 +2589,15 @@ __strfd_dur(
}
res = snprintf(buf, bsz, "%u", d->w);
break;
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_WCNT_MON:
res = snprintf(buf, bsz, "%u", d->c);
break;
case DT_SPFL_S_WDAY:
case DT_SPFL_S_MON:
case DT_SPFL_S_QTR:
case DT_SPFL_N_QTR:
- case DT_SPFL_N_CNT_YEAR:
+ case DT_SPFL_N_DCNT_YEAR:
+ case DT_SPFL_N_WCNT_YEAR:
break;
case DT_SPFL_LIT_PERCENT:
View
@@ -307,14 +307,15 @@ __strpdt_card(struct strpdt_s *d, const char *sp, struct dt_spec_s s, char **ep)
case DT_SPFL_N_DSTD:
case DT_SPFL_N_YEAR:
case DT_SPFL_N_MON:
- case DT_SPFL_N_MDAY:
- case DT_SPFL_N_CNT_WEEK:
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_DCNT_MON:
+ case DT_SPFL_N_DCNT_WEEK:
+ case DT_SPFL_N_DCNT_YEAR:
+ case DT_SPFL_N_WCNT_MON:
+ case DT_SPFL_N_WCNT_YEAR:
case DT_SPFL_S_WDAY:
case DT_SPFL_S_MON:
case DT_SPFL_S_QTR:
case DT_SPFL_N_QTR:
- case DT_SPFL_N_CNT_YEAR:
res = __strpd_card(&d->sd, sp, s, ep);
goto out_direct;
@@ -378,14 +379,15 @@ __strfdt_card(
case DT_SPFL_N_DSTD:
case DT_SPFL_N_YEAR:
case DT_SPFL_N_MON:
- case DT_SPFL_N_MDAY:
- case DT_SPFL_N_CNT_WEEK:
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_DCNT_WEEK:
+ case DT_SPFL_N_DCNT_MON:
+ case DT_SPFL_N_DCNT_YEAR:
+ case DT_SPFL_N_WCNT_MON:
+ case DT_SPFL_N_WCNT_YEAR:
case DT_SPFL_S_WDAY:
case DT_SPFL_S_MON:
case DT_SPFL_S_QTR:
case DT_SPFL_N_QTR:
- case DT_SPFL_N_CNT_YEAR:
res = __strfd_card(buf, bsz, s, &d->sd, that.d);
break;
@@ -432,16 +434,17 @@ __strfdt_dur(
return 0;
case DT_SPFL_N_DSTD:
- case DT_SPFL_N_MDAY:
case DT_SPFL_N_YEAR:
case DT_SPFL_N_MON:
- case DT_SPFL_N_CNT_WEEK:
- case DT_SPFL_N_CNT_MON:
+ case DT_SPFL_N_DCNT_WEEK:
+ case DT_SPFL_N_DCNT_MON:
+ case DT_SPFL_N_DCNT_YEAR:
+ case DT_SPFL_N_WCNT_MON:
+ case DT_SPFL_N_WCNT_YEAR:
case DT_SPFL_S_WDAY:
case DT_SPFL_S_MON:
case DT_SPFL_S_QTR:
case DT_SPFL_N_QTR:
- case DT_SPFL_N_CNT_YEAR:
return __strfd_dur(buf, bsz, s, &d->sd, that.d);
/* noone's ever bothered doing the same thing for times */
Oops, something went wrong.

0 comments on commit dd3fd48

Please sign in to comment.