summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/clock.n34
-rw-r--r--generic/tclClock.c17
-rw-r--r--generic/tclClockFmt.c146
-rw-r--r--generic/tclDate.h2
-rw-r--r--tests/clock.test206
5 files changed, 337 insertions, 68 deletions
diff --git a/doc/clock.n b/doc/clock.n
index 0dae993..d75f32d 100644
--- a/doc/clock.n
+++ b/doc/clock.n
@@ -398,8 +398,12 @@ preprocessed format string. In order of preference:
If the string contains a \fB%s\fR format group, representing
seconds from the epoch, that group is used to determine the date.
.IP [2]
-If the string contains a \fB%J\fR format group, representing
-the Julian Day Number, that group is used to determine the date.
+If the string contains a \fB%J\fR, \fB%EJ\fR or \fB%Ej\fR format groups,
+representing the Calendar or Astronomical Julian Day Number, that groups
+are used to determine the date.
+Note, that in case of \fB%EJ\fR or \fB%Ej\fR format groups, representing
+the Julian Date with time fraction, this groups may be used to determine
+the date and time.
.IP [3]
If the string contains a complete set of format groups specifying
century, year, month, and day of month; century, year, and day of year;
@@ -550,6 +554,30 @@ abbreviation appropriate to the current locale, and uses it to fix
whether \fB%Y\fR refers to years before or after Year 1 of the
Common Era.
.TP
+\fB%Ej\fR
+On output, produces a string of digits giving the Astronomical Julian Date or
+Astronomical Julian Day Number (JDN/JD). In opposite to calendar julian day
+\fB%J\fR, it starts the day at noon.
+On input, accepts a string of digits (or floating point with the time fraction)
+and interprets it as an Astronomical Julian Day Number (JDN/JD).
+The Astronomical Julian Date is a count of the number of calendar days
+that have elapsed since 1 January, 4713 BCE of the proleptic
+Julian calendar, which contains also the time fraktion (after floating point).
+The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440587.5.
+This value corresponds the julian day used in sqlite-database, and is the same
+as result of \fBselect julianday(:seconds, 'unixepoch')\fR.
+.TP
+\fB%EJ\fR
+On output, produces a string of digits giving the Calendar Julian Date.
+In opposite to julian day \fB%J\fR format group, it produces float number.
+In opposite to astronomical julian day \fB%Ej\fR group, it starts at midnight.
+On input, accepts a string of digits (or floating point with the time fraction)
+and interprets it as a Calendar Julian Day Number.
+The Calendar Julian Date is a count of the number of calendar days
+that have elapsed since 1 January, 4713 BCE of the proleptic
+Julian calendar, which contains also the time fraktion (after floating point).
+The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440588.
+.TP
\fB%Es\fR
This affects similar to \fB%s\fR, but in opposition to \fB%s\fR it parses
or formats local seconds (not the posix seconds).
@@ -605,7 +633,7 @@ On output, produces a three-digit number giving the day of the year
(001-366). On input, accepts such a number.
.TP
\fB%J\fR
-On output, produces a string of digits giving the Julian Day Number.
+On output, produces a string of digits giving the calendar Julian Day Number.
On input, accepts a string of digits and interprets it as a Julian Day Number.
The Julian Day Number is a count of the number of calendar days
that have elapsed since 1 January, 4713 BCE of the proleptic
diff --git a/generic/tclClock.c b/generic/tclClock.c
index 26d327e..7f31411 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -235,7 +235,8 @@ TclClockInit(
data->yearOfCenturySwitch = ClockDefaultCenturySwitch;
data->validMinYear = INT_MIN;
data->validMaxYear = INT_MAX;
- data->maxJulianDay = 5373484; /* corresponds 9999-12-31 23:59:59 per default */
+ /* corresponds max of JDN in sqlite - 9999-12-31 23:59:59 per default */
+ data->maxJDN = 5373484.499999994;
data->systemTimeZone = NULL;
data->systemSetupTZData = NULL;
@@ -1120,17 +1121,17 @@ ClockConfigureObjCmd(
break;
case CLOCK_MAX_JDN:
if (i < objc) {
- Tcl_WideInt jd;
- if (TclGetWideIntFromObj(interp, objv[i], &jd) != TCL_OK) {
+ double jd;
+ if (Tcl_GetDoubleFromObj(interp, objv[i], &jd) != TCL_OK) {
return TCL_ERROR;
}
- dataPtr->maxJulianDay = jd;
+ dataPtr->maxJDN = jd;
Tcl_SetObjResult(interp, objv[i]);
continue;
}
if (i+1 >= objc) {
Tcl_SetObjResult(interp,
- Tcl_NewWideIntObj(dataPtr->maxJulianDay));
+ Tcl_NewDoubleObj(dataPtr->maxJDN));
}
break;
case CLOCK_VALIDATE:
@@ -3719,8 +3720,10 @@ ClockScanCommit(
/* some overflow checks */
if (info->flags & CLF_JULIANDAY) {
- ClockClientData *dataPtr = opts->clientData;
- if (yydate.julianDay > dataPtr->maxJulianDay) {
+ ClockClientData *dataPtr = opts->clientData;
+ double curJDN = (double)yydate.julianDay
+ + ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY;
+ if (curJDN > dataPtr->maxJDN) {
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
"requested date too large to represent", -1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", NULL);
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index 67a2ec4..8e14a7d 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -1584,6 +1584,72 @@ ClockScnToken_LocaleListMatcher_Proc(ClockFmtScnCmdArgs *opts,
}
static int
+ClockScnToken_JDN_Proc(ClockFmtScnCmdArgs *opts,
+ DateInfo *info, ClockScanToken *tok)
+{
+ int minLen, maxLen;
+ register const char *p = yyInput, *end; const char *s;
+ Tcl_WideInt intJD; int fractJD = 0, fractJDDiv = 1;
+
+ DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
+
+ end = yyInput + maxLen;
+
+ /* currently positive astronomic dates only */
+ if (*p == '+' || *p == '-') { p++; };
+ s = p;
+ while (p < end && isdigit(UCHAR(*p))) {
+ p++;
+ }
+ if ( _str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) {
+ return TCL_RETURN;
+ };
+ yyInput = p;
+ if (p >= end || *p++ != '.') { /* allow pure integer JDN */
+ /* by astronomical JD the seconds of day offs is 12 hours */
+ if (tok->map->offs) {
+ goto done;
+ }
+ /* calendar JD */
+ yydate.julianDay = intJD;
+ return TCL_OK;
+ }
+ s = p;
+ while (p < end && isdigit(UCHAR(*p))) {
+ fractJDDiv *= 10;
+ p++;
+ }
+ if ( _str2int(&fractJD, s, p, 1) != TCL_OK) {
+ return TCL_RETURN;
+ };
+ yyInput = p;
+
+done:
+ /*
+ * Build a date from julian day (integer and fraction).
+ * Note, astronomical JDN starts at noon in opposite to calendar julianday.
+ */
+
+ fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */
+ + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv);
+ if (fractJD > SECONDS_PER_DAY) {
+ fractJD %= SECONDS_PER_DAY;
+ intJD += 1;
+ }
+ yydate.secondOfDay = fractJD;
+ yydate.julianDay = intJD;
+
+ yydate.seconds =
+ -210866803200L
+ + ( SECONDS_PER_DAY * intJD )
+ + ( fractJD );
+
+ info->flags |= CLF_POSIXSEC;
+
+ return TCL_OK;
+}
+
+static int
ClockScnToken_TimeZone_Proc(ClockFmtScnCmdArgs *opts,
DateInfo *info, ClockScanToken *tok)
{
@@ -1772,7 +1838,7 @@ static ClockScanTokenMap ScnSTokenMap[] = {
{CTOKT_PARSER, 0, 0, 0, 0xffff, 0,
ClockScnToken_amPmInd_Proc, NULL},
/* %J */
- {CTOKT_WIDE, CLF_JULIANDAY, 0, 1, 0xffff, TclOffset(DateInfo, date.julianDay),
+ {CTOKT_WIDE, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.julianDay),
NULL},
/* %j */
{CTOKT_INT, CLF_DAYOFYEAR, 0, 1, 3, TclOffset(DateInfo, date.dayOfYear),
@@ -1815,11 +1881,17 @@ static const char *ScnSTokenMapAliasIndex[2] = {
};
static const char *ScnETokenMapIndex =
- "Eys";
+ "EJjys";
static ClockScanTokenMap ScnETokenMap[] = {
/* %EE */
{CTOKT_PARSER, 0, 0, 0, 0xffff, TclOffset(DateInfo, date.year),
ClockScnToken_LocaleERA_Proc, (void *)MCLIT_LOCALE_NUMERALS},
+ /* %EJ */
+ {CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, 0, /* calendar JDN starts at midnight */
+ ClockScnToken_JDN_Proc, NULL},
+ /* %Ej */
+ {CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */
+ ClockScnToken_JDN_Proc, NULL},
/* %Ey */
{CTOKT_PARSER, 0, 0, 0, 0xffff, 0, /* currently no capture, parse only token */
ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
@@ -2324,6 +2396,7 @@ ClockScan(
/*
* Invalidate result
*/
+ flags |= info->flags;
/* seconds token (%s) take precedence over all other tokens */
if ((opts->flags & CLF_EXTENDED) || !(flags & CLF_POSIXSEC)) {
@@ -2592,6 +2665,67 @@ ClockFmtToken_WeekOfYear_Proc(
return TCL_OK;
}
static int
+ClockFmtToken_JDN_Proc(
+ ClockFmtScnCmdArgs *opts,
+ DateFormat *dateFmt,
+ ClockFormatToken *tok,
+ int *val)
+ {
+ Tcl_WideInt intJD = dateFmt->date.julianDay;
+ int fractJD;
+
+ /* Convert to JDN parts (regarding start offset) and time fraction */
+ fractJD = dateFmt->date.secondOfDay
+ - (int)tok->map->offs; /* 0 for calendar or 43200 for astro JD */
+ if (fractJD < 0) {
+ intJD--;
+ fractJD += SECONDS_PER_DAY;
+ }
+ if (fractJD && intJD < 0) { /* avoid jump over 0, by negative JD's */
+ intJD++;
+ if (intJD == 0) {
+ /* -0.0 / -0.9 has zero integer part, so append "-" extra */
+ if (FrmResultAllocate(dateFmt, 1) != TCL_OK) { return TCL_ERROR; };
+ *dateFmt->output++ = '-';
+ }
+ /* and inverse seconds of day, -0(75) -> -0.25 as float */
+ fractJD = SECONDS_PER_DAY - fractJD;
+ }
+
+ /* 21 is max width of (negative) wide-int (rather smaller, but anyway a time fraction below) */
+ if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { return TCL_ERROR; };
+ dateFmt->output = _witoaw(dateFmt->output, intJD, '0', 1);
+ /* simplest cases .0 and .5 */
+ if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) {
+ /* point + 0 or 5 */
+ if (FrmResultAllocate(dateFmt, 1+1) != TCL_OK) { return TCL_ERROR; };
+ *dateFmt->output++ = '.';
+ *dateFmt->output++ = !fractJD ? '0' : '5';
+ *dateFmt->output = '\0';
+ return TCL_OK;
+ } else {
+ /* wrap the time fraction */
+ #define JDN_MAX_PRECISION 8
+ #define JDN_MAX_PRECBOUND 100000000 /* 10**JDN_MAX_PRECISION */
+ char *p;
+
+ /* to float (part after floating point, + 0.5 to round it up) */
+ fractJD = (int)(
+ (double)fractJD * JDN_MAX_PRECBOUND / SECONDS_PER_DAY + 0.5
+ );
+ /* point + integer (as time fraction after floating point) */
+ if (FrmResultAllocate(dateFmt, 1+JDN_MAX_PRECISION) != TCL_OK) { return TCL_ERROR; };
+ *dateFmt->output++ = '.';
+ p = _itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION);
+ /* remove trailing zero's */
+ dateFmt->output++;
+ while (p > dateFmt->output && *(p-1) == '0') {p--;}
+ *p = '\0';
+ dateFmt->output = p;
+ }
+ return TCL_OK;
+}
+static int
ClockFmtToken_TimeZone_Proc(
ClockFmtScnCmdArgs *opts,
DateFormat *dateFmt,
@@ -2827,11 +2961,17 @@ static const char *FmtSTokenMapAliasIndex[2] = {
};
static const char *FmtETokenMapIndex =
- "Eys";
+ "EJjys";
static ClockFormatTokenMap FmtETokenMap[] = {
/* %EE */
{CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
ClockFmtToken_LocaleERA_Proc, NULL},
+ /* %EJ */
+ {CFMTT_PROC, NULL, 0, 0, 0, 0, 0, /* calendar JDN starts at midnight */
+ ClockFmtToken_JDN_Proc, NULL},
+ /* %Ej */
+ {CFMTT_PROC, NULL, 0, 0, 0, 0, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */
+ ClockFmtToken_JDN_Proc, NULL},
/* %Ey %EC */
{CTOKT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.year),
ClockFmtToken_LocaleERAYear_Proc, NULL},
diff --git a/generic/tclDate.h b/generic/tclDate.h
index 2751ee5..568aef1 100644
--- a/generic/tclDate.h
+++ b/generic/tclDate.h
@@ -310,7 +310,7 @@ typedef struct ClockClientData {
int yearOfCenturySwitch;
int validMinYear;
int validMaxYear;
- Tcl_WideInt maxJulianDay;
+ double maxJDN;
Tcl_Obj *systemTimeZone;
Tcl_Obj *systemSetupTZData;
diff --git a/tests/clock.test b/tests/clock.test
index 72354c2..8a0ed13 100644
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -15358,32 +15358,32 @@ test clock-4.96 { format time of day 23:59:59 } {
-gmt true
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:59 pm 23:59 59 lix 23:59:59 23:59:59 xxiii h lix m lix s Thu Jan 1 23:59:59 GMT 1970}
-test clock-4.97.1 { format julian day } {
- clock format 0 -format {%J} -gmt true
-} {2440588}
-test clock-4.97.2 { format julian day } {
- clock format 43200 -format {%J} -gmt true
-} {2440588}
-test clock-4.97.3 { format julian day } {
- clock format 86399 -format {%J} -gmt true
-} {2440588}
-test clock-4.97.4 { format julian day } {
- clock format 86400 -format {%J} -gmt true
-} {2440589}
-test clock-4.97.5 { format julian day } {
- clock format 129599 -format {%J} -gmt true
-} {2440589}
-test clock-4.97.6 { format julian day } {
- clock format 129600 -format {%J} -gmt true
-} {2440589}
-test clock-4.97.7 { format julian day } {
+test clock-4.97.1 { format JDN/JD (calendar and astronomical) } {
+ clock format 0 -format {%J %EJ %Ej} -gmt true
+} {2440588 2440588.0 2440587.5}
+test clock-4.97.2 { format JDN/JD (calendar and astronomical) } {
+ clock format 43200 -format {%J %EJ %Ej} -gmt true
+} {2440588 2440588.5 2440588.0}
+test clock-4.97.3 { format JDN/JD (calendar and astronomical) } {
+ clock format 86399 -format {%J %EJ %Ej} -gmt true
+} {2440588 2440588.99998843 2440588.49998843}
+test clock-4.97.4 { format JDN/JD (calendar and astronomical) } {
+ clock format 86400 -format {%J %EJ %Ej} -gmt true
+} {2440589 2440589.0 2440588.5}
+test clock-4.97.5 { format JDN/JD (calendar and astronomical) } {
+ clock format 129599 -format {%J %EJ %Ej} -gmt true
+} {2440589 2440589.49998843 2440588.99998843}
+test clock-4.97.6 { format JDN/JD (calendar and astronomical) } {
+ clock format 129600 -format {%J %EJ %Ej} -gmt true
+} {2440589 2440589.5 2440589.0}
+test clock-4.97.7 { format JDN/JD (calendar and astronomical) } {
set i 1548249092
list \
- [clock format $i -format {%J} -gmt true] \
- [clock format [incr i] -format {%J} -gmt true] \
- [clock format [incr i] -format {%J} -gmt true]
-} {2458507 2458507 2458507}
-test clock-4.97.8 { format julian day } {
+ [clock format $i -format {%J %EJ %Ej} -gmt true] \
+ [clock format [incr i] -format {%J %EJ %Ej} -gmt true] \
+ [clock format [incr i] -format {%J %EJ %Ej} -gmt true]
+} {{2458507 2458507.54967593 2458507.04967593} {2458507 2458507.5496875 2458507.0496875} {2458507 2458507.54969907 2458507.04969907}}
+test clock-4.97.8 { format JDN/JD (calendar and astronomical) } {
set res {}
foreach i {
-172800 -129600 -86400 -43200
@@ -15391,26 +15391,26 @@ test clock-4.97.8 { format julian day } {
86400 86401 108000 129600 172800
} {
lappend res $i [clock format [expr -210866803200 - $i] \
- -format {%EE %Y-%m-%d %T -- %J} -gmt true]
+ -format {%EE %Y-%m-%d %T -- %J %EJ %Ej} -gmt true]
}
set res
} [list \
- -172800 {B.C.E. 4713-01-03 00:00:00 -- 0000002} \
- -129600 {B.C.E. 4713-01-02 12:00:00 -- 0000001} \
- -86400 {B.C.E. 4713-01-02 00:00:00 -- 0000001} \
- -43200 {B.C.E. 4713-01-01 12:00:00 -- 0000000} \
- -1 {B.C.E. 4713-01-01 00:00:01 -- 0000000} \
- 0 {B.C.E. 4713-01-01 00:00:00 -- 0000000} \
- 1 {B.C.E. 4714-12-31 23:59:59 -- -000001} \
- 21600 {B.C.E. 4714-12-31 18:00:00 -- -000001} \
- 43199 {B.C.E. 4714-12-31 12:00:01 -- -000001} \
- 43200 {B.C.E. 4714-12-31 12:00:00 -- -000001} \
- 86399 {B.C.E. 4714-12-31 00:00:01 -- -000001} \
- 86400 {B.C.E. 4714-12-31 00:00:00 -- -000001} \
- 86401 {B.C.E. 4714-12-30 23:59:59 -- -000002} \
- 108000 {B.C.E. 4714-12-30 18:00:00 -- -000002} \
- 129600 {B.C.E. 4714-12-30 12:00:00 -- -000002} \
- 172800 {B.C.E. 4714-12-30 00:00:00 -- -000002} \
+ -172800 {B.C.E. 4713-01-03 00:00:00 -- 0000002 2.0 1.5} \
+ -129600 {B.C.E. 4713-01-02 12:00:00 -- 0000001 1.5 1.0} \
+ -86400 {B.C.E. 4713-01-02 00:00:00 -- 0000001 1.0 0.5} \
+ -43200 {B.C.E. 4713-01-01 12:00:00 -- 0000000 0.5 0.0} \
+ -1 {B.C.E. 4713-01-01 00:00:01 -- 0000000 0.00001157 -0.49998843} \
+ 0 {B.C.E. 4713-01-01 00:00:00 -- 0000000 0.0 -0.5} \
+ 1 {B.C.E. 4714-12-31 23:59:59 -- -000001 -0.00001157 -0.50001157} \
+ 21600 {B.C.E. 4714-12-31 18:00:00 -- -000001 -0.25 -0.75} \
+ 43199 {B.C.E. 4714-12-31 12:00:01 -- -000001 -0.49998843 -0.99998843} \
+ 43200 {B.C.E. 4714-12-31 12:00:00 -- -000001 -0.5 -1.0} \
+ 86399 {B.C.E. 4714-12-31 00:00:01 -- -000001 -0.99998843 -1.49998843} \
+ 86400 {B.C.E. 4714-12-31 00:00:00 -- -000001 -1.0 -1.5} \
+ 86401 {B.C.E. 4714-12-30 23:59:59 -- -000002 -1.00001157 -1.50001157} \
+ 108000 {B.C.E. 4714-12-30 18:00:00 -- -000002 -1.25 -1.75} \
+ 129600 {B.C.E. 4714-12-30 12:00:00 -- -000002 -1.5 -2.0} \
+ 172800 {B.C.E. 4714-12-30 00:00:00 -- -000002 -2.0 -2.5} \
]
test clock-4.97.9 { format JDN/JD (calendar and astronomical) } {
set res {}
@@ -15420,19 +15420,19 @@ test clock-4.97.9 { format JDN/JD (calendar and astronomical) } {
43199 43200 43201 86400
} {
lappend res $i [clock format [expr 653133196800 + $i] \
- -format {%Y-%m-%d %T -- %J} -gmt true]
+ -format {%Y-%m-%d %T -- %J %EJ %Ej} -gmt true]
}
set res
} [list \
- -86400 {22666-12-19 00:00:00 -- 9999999} \
- -43200 {22666-12-19 12:00:00 -- 9999999} \
- -1 {22666-12-19 23:59:59 -- 9999999} \
- 0 {22666-12-20 00:00:00 -- 10000000} \
- 1 {22666-12-20 00:00:01 -- 10000000} \
- 43199 {22666-12-20 11:59:59 -- 10000000} \
- 43200 {22666-12-20 12:00:00 -- 10000000} \
- 43201 {22666-12-20 12:00:01 -- 10000000} \
- 86400 {22666-12-21 00:00:00 -- 10000001} \
+ -86400 {22666-12-19 00:00:00 -- 9999999 9999999.0 9999998.5} \
+ -43200 {22666-12-19 12:00:00 -- 9999999 9999999.5 9999999.0} \
+ -1 {22666-12-19 23:59:59 -- 9999999 9999999.99998843 9999999.49998843} \
+ 0 {22666-12-20 00:00:00 -- 10000000 10000000.0 9999999.5} \
+ 1 {22666-12-20 00:00:01 -- 10000000 10000000.00001157 9999999.50001157} \
+ 43199 {22666-12-20 11:59:59 -- 10000000 10000000.49998843 9999999.99998843} \
+ 43200 {22666-12-20 12:00:00 -- 10000000 10000000.5 10000000.0} \
+ 43201 {22666-12-20 12:00:01 -- 10000000 10000000.50001157 10000000.00001157} \
+ 86400 {22666-12-21 00:00:00 -- 10000001 10000001.0 10000000.5} \
]
# END testcases4
@@ -18899,6 +18899,91 @@ test clock-7.8 {Julian Day, precedence below seconds} {
test clock-7.9 {Julian Day, two values} {
clock scan {2440588 2440589} -format {%J %J} -gmt true
} 86400
+test clock-7.10 {Calendar vs Astronomical Julian Day (without and with time fraction)} {
+ list \
+ [clock scan {2440588} -format {%J} -gmt true] \
+ [clock scan {2440588} -format {%EJ} -gmt true] \
+ [clock scan {2440588} -format {%Ej} -gmt true] \
+ [clock scan {2440588.5} -format {%EJ} -gmt true] \
+ [clock scan {2440588.5} -format {%Ej} -gmt true] \
+} {0 0 43200 43200 86400}
+
+
+test clock-7.11 {Astronomical JDN/JD} {
+ clock scan 0 -format %Ej -gmt true
+} -210866760000
+
+test clock-7.12 {Astronomical JDN/JD} {
+ clock format [clock scan 2440587.5 -format %Ej -gmt true] \
+ -format "%Y-%m-%d %T" -gmt true
+} "1970-01-01 00:00:00"
+
+test clock-7.13 {Astronomical JDN/JD} {
+ clock format [clock scan 2451544.5 -format %Ej -gmt true] \
+ -format "%Y-%m-%d %T" -gmt true
+} "2000-01-01 00:00:00"
+
+test clock-7.13.1 {Astronomical JDN/JD} {
+ clock format [clock scan 2488069.5 -format %Ej -gmt true] \
+ -format "%Y-%m-%d %T" -gmt true
+} "2100-01-01 00:00:00"
+
+test clock-7.14 {Astronomical JDN/JD} {
+ clock format [clock scan 5373483.5 -format %Ej -gmt true] \
+ -format "%Y-%m-%d %T" -gmt true
+} "9999-12-31 00:00:00"
+
+test clock-7.14.1 {Astronomical JDN/JD} {
+ clock format [clock scan 5373484 -format %Ej -gmt true] \
+ -format "%Y-%m-%d %T" -gmt true
+} "9999-12-31 12:00:00"
+test clock-7.14.2 {Astronomical JDN/JD} {
+ clock format [clock scan 5373484.49999 -format %Ej -gmt true] \
+ -format "%Y-%m-%d %T" -gmt true
+} "9999-12-31 23:59:59"
+
+test clock-7.15 {Astronomical JDN/JD, bad} {
+ list [catch {
+ clock scan bogus -format %Ej
+ } result] $result $errorCode
+} {1 {input string does not match supplied format} {CLOCK badInputString}}
+
+test clock-7.16 {Astronomical JDN/JD, overflow} {
+ list [catch {
+ clock scan 5373484.5 -format %Ej
+ } result] $result $errorCode \
+ [catch {
+ clock scan 5373485 -format %Ej
+ } result] $result $errorCode \
+ [catch {
+ clock scan 2147483648 -format %Ej
+ } result] $result $errorCode \
+ [catch {
+ clock scan 2147483648.5 -format %Ej
+ } result] $result $errorCode
+} [lrepeat 4 1 {requested date too large to represent} {CLOCK dateTooLarge}]
+
+test clock-7.18 {Astronomical JDN/JD, same precedence as seconds (last wins} {
+ list [clock scan {2440588 86400} -format {%Ej %s} -gmt true] \
+ [clock scan {2440589 0} -format {%Ej %s} -gmt true] \
+ [clock scan {86400 2440588} -format {%s %Ej} -gmt true] \
+ [clock scan {0 2440589} -format {%s %Ej} -gmt true]
+} {86400 0 43200 129600}
+
+test clock-7.19 {Astronomical JDN/JD, two values} {
+ clock scan {2440588 2440589} -format {%Ej %Ej} -gmt true
+} 129600
+
+test clock-7.20 {all JDN/JD are signed (and extended accept floats)} {
+ set res {}
+ foreach i {%J %EJ %Ej} {
+ lappend res [clock scan "-1" -format $i -gmt 1]
+ }
+ foreach i {%EJ %Ej} {
+ lappend res [clock scan "-1.5" -format $i -gmt 1]
+ }
+ set res
+} {-210866889600 -210866889600 -210866846400 -210866846400 -210866803200}
# BEGIN testcases8
@@ -21310,9 +21395,22 @@ test clock-9.1 {seconds take precedence over ccyymmdd} {
clock scan {0 20000101} -format {%s %Y%m%d} -gmt true
} 0
-test clock-9.2 {Julian day takes precedence over ccyymmdd} {
- clock scan {2440588 20000101} -format {%J %Y%m%d} -gmt true
-} 0
+test clock-9.2 {Calendar julian day takes precedence over ccyymmdd} {
+ list \
+ [clock scan {2440588 20000101} -format {%J %Y%m%d} -gmt true] \
+ [clock scan {2440588 20000101} -format {%EJ %Y%m%d} -gmt true]
+} {0 0}
+test clock-9.2.1 {Calendar julian day (with time fraction) takes precedence over date-time} {
+ list \
+ [clock scan {2440588.0 20000101 010203} -format {%EJ %Y%m%d %H%M%S} -gmt true] \
+ [clock scan {2440588.5 20000101 010203} -format {%EJ %Y%m%d %H%M%S} -gmt true]
+
+} {0 43200}
+test clock-9.3 {Astro julian day takes always precedence over date-time} {
+ list \
+ [clock scan {2440587.5 20000101 010203} -format {%Ej %Y%m%d %H%M%S} -gmt true] \
+ [clock scan {2440588 20000101 010203} -format {%Ej %Y%m%d %H%M%S} -gmt true]
+} {0 43200}
# Test parsing of ccyyddd