summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-01-10 22:31:43 (GMT)
committersebres <sebres@users.sourceforge.net>2017-01-10 22:31:43 (GMT)
commit8fb97e54a5d09f6cb6faab31efe48b7dd0670467 (patch)
treec80d243dd416f4639b531223fac6dee36faaacbb
parent767da780e6fab9b52c9cbe460f6b3101910367e9 (diff)
downloadtcl-8fb97e54a5d09f6cb6faab31efe48b7dd0670467.zip
tcl-8fb97e54a5d09f6cb6faab31efe48b7dd0670467.tar.gz
tcl-8fb97e54a5d09f6cb6faab31efe48b7dd0670467.tar.bz2
%j token as day of year; clear flags implemented (to provide last-wins functionality)
-rw-r--r--generic/tclClock.c86
-rw-r--r--generic/tclClockFmt.c48
-rw-r--r--generic/tclDate.h22
3 files changed, 103 insertions, 53 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index 08bc6ef..ef0e46b 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -2313,7 +2313,47 @@ GetJulianDayFromEraYearMonthDay(
+ ym1o4;
}
}
+/*
+ *----------------------------------------------------------------------
+ */
+static void
+GetJulianDayFromEraYearDay(
+ TclDateFields *fields, /* Date to convert */
+ int changeover) /* Gregorian transition date as a Julian Day */
+{
+ int year, ym1;
+
+ /* Get absolute year number from the civil year */
+ if (fields->era == BCE) {
+ year = 1 - fields->year;
+ } else {
+ year = fields->year;
+ }
+
+ ym1 = year - 1;
+
+ /* Try the Gregorian calendar first. */
+ fields->gregorian = 1;
+ fields->julianDay =
+ 1721425
+ + fields->dayOfYear
+ + ( 365 * ym1 )
+ + ( ym1 / 4 )
+ - ( ym1 / 100 )
+ + ( ym1 / 400 );
+
+ /* If the date is before the Gregorian change, use the Julian calendar. */
+
+ if ( fields->julianDay < changeover ) {
+ fields->gregorian = 0;
+ fields->julianDay =
+ 1721423
+ + fields->dayOfYear
+ + ( 365 * ym1 )
+ + ( ym1 / 4 );
+ }
+}
/*
*----------------------------------------------------------------------
*
@@ -2906,9 +2946,13 @@ ClockScanObjCmd(
goto done;
}
- /* If needed assemble julianDay using new year, month, etc. */
- if (info->flags & CLF_INVALIDATE_JULIANDAY) {
- GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
+ /* If needed assemble julianDay using year, month, etc. */
+ if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
+ if ((info->flags & CLF_DAYOFMONTH) || !(info->flags & CLF_DAYOFYEAR)) {
+ GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
+ } else {
+ GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
+ }
}
/* some overflow checks, if not extended */
@@ -2924,7 +2968,7 @@ ClockScanObjCmd(
/* Local seconds to UTC (stored in yydate.seconds) */
- if (info->flags & (CLF_INVALIDATE_SECONDS|CLF_INVALIDATE_JULIANDAY)) {
+ if (info->flags & (CLF_ASSEMBLE_SECONDS|CLF_ASSEMBLE_JULIANDAY)) {
yydate.localSeconds =
-210866803200L
+ ( SECONDS_PER_DAY * (Tcl_WideInt)yydate.julianDay )
@@ -3007,7 +3051,7 @@ ClockFreeScan(
if (yyHaveTime == 0) {
yyHaveTime = -1;
}
- info->flags |= CLF_INVALIDATE_JULIANDAY|CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
}
/*
@@ -3032,7 +3076,7 @@ ClockFreeScan(
// Tcl_SetObjRef(yydate.tzName, opts->timezoneObj);
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
}
/*
@@ -3041,13 +3085,13 @@ ClockFreeScan(
if (yyHaveTime == -1) {
yySeconds = 0;
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
}
else
if (yyHaveTime) {
yySeconds = ToSeconds(yyHour, yyMinutes,
yySeconds, yyMeridian);
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
}
else
if ( (yyHaveDay && !yyHaveDate)
@@ -3057,7 +3101,7 @@ ClockFreeScan(
|| yyRelDay != 0 ) )
) {
yySeconds = 0;
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
}
else {
yySeconds = yydate.localSeconds % SECONDS_PER_DAY;
@@ -3084,11 +3128,11 @@ repeat_rel:
int m, h;
/* if needed extract year, month, etc. again */
- if (info->flags & CLF_INVALIDATE_DATE) {
+ if (info->flags & CLF_ASSEMBLE_DATE) {
GetGregorianEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
GetMonthDay(&yydate);
GetYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
- info->flags &= ~CLF_INVALIDATE_DATE;
+ info->flags &= ~CLF_ASSEMBLE_DATE;
}
/* add the requisite number of months */
@@ -3104,7 +3148,7 @@ repeat_rel:
}
/* on demand (lazy) assemble julianDay using new year, month, etc. */
- info->flags |= CLF_INVALIDATE_JULIANDAY|CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
yyRelMonth = 0;
}
@@ -3113,14 +3157,14 @@ repeat_rel:
if (yyRelDay) {
/* assemble julianDay using new year, month, etc. */
- if (info->flags & CLF_INVALIDATE_JULIANDAY) {
+ if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
- info->flags &= ~CLF_INVALIDATE_JULIANDAY;
+ info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
yydate.julianDay += yyRelDay;
/* julianDay was changed, on demand (lazy) extract year, month, etc. again */
- info->flags |= CLF_INVALIDATE_DATE|CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
yyRelDay = 0;
}
@@ -3150,11 +3194,11 @@ repeat_rel:
int monthDiff;
/* if needed extract year, month, etc. again */
- if (info->flags & CLF_INVALIDATE_DATE) {
+ if (info->flags & CLF_ASSEMBLE_DATE) {
GetGregorianEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
GetMonthDay(&yydate);
GetYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
- info->flags &= ~CLF_INVALIDATE_DATE;
+ info->flags &= ~CLF_ASSEMBLE_DATE;
}
if (yyMonthOrdinalIncr > 0) {
@@ -3177,7 +3221,7 @@ repeat_rel:
yyRelMonth += monthDiff;
yyHaveOrdinalMonth = 0;
- info->flags |= CLF_INVALIDATE_JULIANDAY|CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
goto repeat_rel;
}
@@ -3189,9 +3233,9 @@ repeat_rel:
if (yyHaveDay && !yyHaveDate) {
/* if needed assemble julianDay now */
- if (info->flags & CLF_INVALIDATE_JULIANDAY) {
+ if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
- info->flags &= ~CLF_INVALIDATE_JULIANDAY;
+ info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
yydate.era = CE;
@@ -3200,7 +3244,7 @@ repeat_rel:
if (yyDayOrdinal > 0) {
yydate.julianDay -= 7;
}
- info->flags |= CLF_INVALIDATE_DATE|CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
}
/* Free scanning completed - date ready */
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index ba924fd..2c1dfc1 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -678,40 +678,43 @@ ClockScnToken_LocaleListMatcher_Proc(ClockFmtScnCmdArgs *opts,
static const char *ScnSTokenMapIndex =
- "dmbyYHMSJCs";
+ "dmbyYHMSJjCs";
static ClockScanTokenMap ScnSTokenMap[] = {
/* %d %e */
- {CTOKT_DIGIT, CLF_DATE, 1, 2, TclOffset(DateInfo, date.dayOfMonth),
+ {CTOKT_DIGIT, CLF_DATE | CLF_DAYOFMONTH, CLF_DAYOFYEAR, 1, 2, TclOffset(DateInfo, date.dayOfMonth),
NULL},
/* %m */
- {CTOKT_DIGIT, CLF_DATE, 1, 2, TclOffset(DateInfo, date.month),
+ {CTOKT_DIGIT, CLF_DATE, CLF_DAYOFYEAR, 1, 2, TclOffset(DateInfo, date.month),
NULL},
/* %b %B %h */
- {CTOKT_PARSER, CLF_DATE, 0, 0, 0,
+ {CTOKT_PARSER, CLF_DATE, CLF_DAYOFYEAR, 0, 0, 0,
ClockScnToken_Month_Proc},
/* %y */
- {CTOKT_DIGIT, CLF_DATE, 1, 2, TclOffset(DateInfo, date.year),
+ {CTOKT_DIGIT, CLF_DATE, 0, 1, 2, TclOffset(DateInfo, date.year),
NULL},
/* %Y */
- {CTOKT_DIGIT, CLF_DATE | CLF_CENTURY, 1, 4, TclOffset(DateInfo, date.year),
+ {CTOKT_DIGIT, CLF_DATE | CLF_CENTURY, 0, 1, 4, TclOffset(DateInfo, date.year),
NULL},
/* %H */
- {CTOKT_DIGIT, CLF_TIME, 1, 2, TclOffset(DateInfo, date.hour),
+ {CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.hour),
NULL},
/* %M */
- {CTOKT_DIGIT, CLF_TIME, 1, 2, TclOffset(DateInfo, date.minutes),
+ {CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.minutes),
NULL},
/* %S */
- {CTOKT_DIGIT, CLF_TIME, 1, 2, TclOffset(DateInfo, date.secondOfDay),
+ {CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.secondOfDay),
NULL},
/* %J */
- {CTOKT_DIGIT, CLF_DATE | CLF_JULIANDAY, 1, 0xffff, TclOffset(DateInfo, date.julianDay),
+ {CTOKT_DIGIT, CLF_DATE | CLF_JULIANDAY, 0, 1, 0xffff, TclOffset(DateInfo, date.julianDay),
+ NULL},
+ /* %j */
+ {CTOKT_DIGIT, CLF_DATE | CLF_DAYOFYEAR, CLF_DAYOFMONTH, 1, 3, TclOffset(DateInfo, date.dayOfYear),
NULL},
/* %C */
- {CTOKT_DIGIT, CLF_DATE | CLF_CENTURY, 1, 2, TclOffset(DateInfo, dateCentury),
+ {CTOKT_DIGIT, CLF_DATE | CLF_CENTURY, 0, 1, 2, TclOffset(DateInfo, dateCentury),
NULL},
/* %s */
- {CTOKT_DIGIT, CLF_LOCALSEC | CLF_SIGNED, 1, 0xffff, TclOffset(DateInfo, date.localSeconds),
+ {CTOKT_DIGIT, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.localSeconds),
NULL},
};
static const char *ScnSTokenWrapMapIndex[2] = {
@@ -733,10 +736,10 @@ static const char *ScnOTokenMapIndex =
"dm";
static ClockScanTokenMap ScnOTokenMap[] = {
/* %Od %Oe */
- {CTOKT_PARSER, CLF_DATE, 0, 0, TclOffset(DateInfo, date.dayOfMonth),
+ {CTOKT_PARSER, CLF_DATE | CLF_DAYOFMONTH, CLF_DAYOFYEAR, 0, 0, TclOffset(DateInfo, date.dayOfMonth),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %Om */
- {CTOKT_PARSER, CLF_DATE, 0, 0, TclOffset(DateInfo, date.month),
+ {CTOKT_PARSER, CLF_DATE, CLF_DAYOFYEAR, 0, 0, TclOffset(DateInfo, date.month),
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
};
static const char *ScnOTokenWrapMapIndex[2] = {
@@ -747,12 +750,12 @@ static const char *ScnOTokenWrapMapIndex[2] = {
static const char *ScnSpecTokenMapIndex =
" ";
static ClockScanTokenMap ScnSpecTokenMap[] = {
- {CTOKT_SPACE, 0, 1, 0xffff, 0,
+ {CTOKT_SPACE, 0, 0, 1, 0xffff, 0,
NULL},
};
static ClockScanTokenMap ScnWordTokenMap = {
- CTOKT_WORD, 0, 1, 0, 0,
+ CTOKT_WORD, 0, 0, 1, 0, 0,
NULL
};
@@ -1095,7 +1098,7 @@ ClockScan(
}
p = x;
}
- flags |= map->flags;
+ flags = (flags & ~map->clearFlags) | map->flags;
}
break;
case CTOKT_PARSER:
@@ -1110,7 +1113,7 @@ ClockScan(
break;
};
p = yyInput;
- flags |= map->flags;
+ flags = (flags & ~map->clearFlags) | map->flags;
break;
case CTOKT_SPACE:
/* at least one space in strict mode */
@@ -1150,13 +1153,14 @@ ClockScan(
/*
* Invalidate result
*/
+ info->flags |= flags;
/* seconds token (%s) take precedence over all other tokens */
if ((opts->flags & CLF_EXTENDED) || !(flags & CLF_LOCALSEC)) {
if (flags & CLF_DATE) {
if (!(flags & CLF_JULIANDAY)) {
- info->flags |= CLF_INVALIDATE_SECONDS|CLF_INVALIDATE_JULIANDAY;
+ info->flags |= CLF_ASSEMBLE_SECONDS|CLF_ASSEMBLE_JULIANDAY;
if (yyYear < 100) {
if (!(flags & CLF_CENTURY)) {
@@ -1172,18 +1176,18 @@ ClockScan(
}
/* if date but no time - reset time */
if (!(flags & (CLF_TIME|CLF_LOCALSEC))) {
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
yydate.localSeconds = 0;
}
}
if (flags & CLF_TIME) {
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
yySeconds = ToSeconds(yyHour, yyMinutes,
yySeconds, yyMeridian);
} else
if (!(flags & CLF_LOCALSEC)) {
- info->flags |= CLF_INVALIDATE_SECONDS;
+ info->flags |= CLF_ASSEMBLE_SECONDS;
yySeconds = yydate.localSeconds % SECONDS_PER_DAY;
}
}
diff --git a/generic/tclDate.h b/generic/tclDate.h
index 9f65b1b..23fe5b3 100644
--- a/generic/tclDate.h
+++ b/generic/tclDate.h
@@ -30,10 +30,18 @@
#define ONE_YEAR 365 /* days */
+#define CLF_DATE (1 << 2)
+#define CLF_JULIANDAY (1 << 3)
+#define CLF_TIME (1 << 4)
+#define CLF_LOCALSEC (1 << 5)
+#define CLF_CENTURY (1 << 6)
+#define CLF_DAYOFMONTH (1 << 7)
+#define CLF_DAYOFYEAR (1 << 8)
+#define CLF_SIGNED (1 << 15)
/* On demand (lazy) assemble flags */
-#define CLF_INVALIDATE_DATE (1 << 6) /* assemble year, month, etc. using julianDay */
-#define CLF_INVALIDATE_JULIANDAY (1 << 7) /* assemble julianDay using year, month, etc. */
-#define CLF_INVALIDATE_SECONDS (1 << 8) /* assemble localSeconds (and seconds at end) */
+#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */
+#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */
+#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */
/*
@@ -339,13 +347,6 @@ typedef int ClockScanTokenProc(
ClockScanToken *tok);
-#define CLF_DATE (1 << 2)
-#define CLF_JULIANDAY (1 << 3)
-#define CLF_TIME (1 << 4)
-#define CLF_LOCALSEC (1 << 5)
-#define CLF_CENTURY (1 << 6)
-#define CLF_SIGNED (1 << 8)
-
typedef enum _CLCKTOK_TYPE {
CTOKT_DIGIT = 1, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD
} CLCKTOK_TYPE;
@@ -359,6 +360,7 @@ typedef struct ClockFormatToken {
typedef struct ClockScanTokenMap {
unsigned short int type;
unsigned short int flags;
+ unsigned short int clearFlags;
unsigned short int minSize;
unsigned short int maxSize;
unsigned short int offs;