From 35d4ffd9a74d652788b42a6c8300dbf3c2a62eb6 Mon Sep 17 00:00:00 2001 From: ericm Date: Fri, 14 Jan 2000 22:15:51 +0000 Subject: * unix/tclUnixTime.c: New clock format format. * compat/strftime.c: New clock format format. * generic/tclGetDate.y: New clock scan format. --- compat/strftime.c | 14 ++- generic/tclDate.c | 259 ++++++++++++++++++++++++++++----------------------- generic/tclGetDate.y | 37 ++++++-- tests/clock.test | 10 +- unix/tclUnixTime.c | 13 ++- 5 files changed, 196 insertions(+), 137 deletions(-) diff --git a/compat/strftime.c b/compat/strftime.c index bb8ea52..1c14ca8 100644 --- a/compat/strftime.c +++ b/compat/strftime.c @@ -8,7 +8,7 @@ * source. See the copyright notice below for details on redistribution * restrictions. The "license.terms" file does not apply to this file. * - * RCS: @(#) $Id: strftime.c,v 1.5 1999/07/22 01:26:18 redman Exp $ + * RCS: @(#) $Id: strftime.c,v 1.6 2000/01/14 22:15:51 ericm Exp $ */ /* @@ -45,7 +45,7 @@ */ #if defined(LIBC_SCCS) -static char *rcsid = "$Id: strftime.c,v 1.5 1999/07/22 01:26:18 redman Exp $"; +static char *rcsid = "$Id: strftime.c,v 1.6 2000/01/14 22:15:51 ericm Exp $"; #endif /* LIBC_SCCS */ #include @@ -111,6 +111,16 @@ TclpStrftime(s, maxsize, format, t) const char *format; const struct tm *t; { + if (format[0] == '%' && format[1] == 'Q') { + /* Format as a stardate */ + sprintf(s, "Stardate %2d%03d.%01d", + (((t->tm_year + TM_YEAR_BASE) + 377) - 2323), + (((t->tm_yday + 1) * 1000) / + (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))), + (((t->tm_hour * 60) + t->tm_min)/144)); + return(strlen(s)); + } + tzset(); pt = s; diff --git a/generic/tclDate.c b/generic/tclDate.c index b88156b..87ab0fb 100644 --- a/generic/tclDate.c +++ b/generic/tclDate.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclDate.c,v 1.14 2000/01/12 23:35:52 ericm Exp $ + * RCS: @(#) $Id: tclDate.c,v 1.15 2000/01/14 22:15:51 ericm Exp $ */ #include "tclInt.h" @@ -37,7 +37,7 @@ #define HOUR(x) ((int) (60 * x)) #define SECSPERDAY (24L * 60L * 60L) - +#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) /* * An entry in the lexical lookup table. @@ -129,15 +129,16 @@ typedef union # define tMINUTE_UNIT 262 # define tMONTH 263 # define tMONTH_UNIT 264 -# define tSEC_UNIT 265 -# define tSNUMBER 266 -# define tUNUMBER 267 -# define tZONE 268 -# define tEPOCH 269 -# define tDST 270 -# define tISOBASE 271 -# define tDAY_UNIT 272 -# define tNEXT 273 +# define tSTARDATE 265 +# define tSEC_UNIT 266 +# define tSNUMBER 267 +# define tUNUMBER 268 +# define tZONE 269 +# define tEPOCH 270 +# define tDST 271 +# define tISOBASE 272 +# define tDAY_UNIT 273 +# define tNEXT 274 @@ -258,6 +259,7 @@ static TABLE OtherTable[] = { #endif { "ago", tAGO, 1 }, { "epoch", tEPOCH, 0 }, + { "stardate", tSTARDATE, 0}, { NULL } }; @@ -452,8 +454,7 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr) * But, every year divisible by 100 is not a leap year. * But, every year divisible by 400 is a leap year after all. */ - DaysInMonth[1] = (Year % 4 == 0) && (Year % 100 != 0 || Year % 400 == 0) - ? 29 : 28; + DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28; /* Check the inputs for validity */ if (Month < 1 || Month > 12 @@ -468,12 +469,10 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr) Julian += DaysInMonth[i]; if (Year >= EPOCH) { for (i = EPOCH; i < Year; i++) - Julian += 365 + (((i % 4) == 0) && - (((i % 100) != 0) || ((i % 400) == 0))); + Julian += 365 + IsLeapYear(i); } else { for (i = Year; i < EPOCH; i++) - Julian -= 365 + (((i % 4) == 0) && - (((i % 100) != 0) || ((i % 400) == 0))); + Julian -= 365 + IsLeapYear(i); } Julian *= SECSPERDAY; @@ -881,21 +880,21 @@ static CONST TclDatetabelem TclDateexca[] ={ 0, -1, -2, 0, }; -# define YYNPROD 51 -# define YYLAST 256 +# define YYNPROD 53 +# define YYLAST 259 static CONST TclDatetabelem TclDateact[]={ - 21, 38, 20, 33, 32, 52, 34, 24, 22, 75, - 40, 24, 22, 24, 22, 23, 72, 74, 29, 23, - 28, 23, 50, 45, 70, 69, 49, 46, 68, 67, - 66, 26, 65, 63, 47, 44, 43, 37, 35, 56, - 42, 55, 73, 62, 41, 59, 61, 60, 51, 36, - 19, 9, 57, 8, 7, 6, 5, 4, 3, 2, - 1, 31, 17, 0, 0, 0, 0, 0, 0, 39, - 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, - 0, 54, 0, 0, 0, 0, 0, 0, 64, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 71, 0, + 23, 40, 22, 34, 26, 35, 24, 26, 36, 24, + 53, 42, 55, 25, 52, 80, 25, 79, 26, 31, + 24, 30, 59, 48, 75, 74, 73, 25, 49, 72, + 71, 70, 28, 69, 67, 50, 47, 46, 45, 39, + 37, 60, 77, 44, 78, 66, 43, 63, 58, 20, + 65, 64, 54, 38, 61, 10, 9, 8, 7, 6, + 5, 33, 4, 3, 2, 1, 18, 0, 0, 41, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 0, 56, + 0, 0, 57, 0, 76, 0, 0, 0, 0, 0, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -906,61 +905,64 @@ static CONST TclDatetabelem TclDateact[]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 16, 12, 0, 0, 0, - 14, 24, 22, 0, 10, 11, 15, 0, 13, 23, - 18, 27, 58, 0, 25, 0, 30, 24, 22, 0, - 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 58 }; + 0, 0, 0, 0, 0, 17, 13, 0, 0, 0, + 15, 26, 21, 24, 0, 11, 12, 16, 0, 14, + 25, 19, 29, 0, 0, 27, 0, 32, 26, 0, + 24, 0, 0, 0, 0, 0, 0, 25, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 62, 62 }; static CONST TclDatetabelem TclDatepact[]={ -10000000, -43,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, - -27, -266,-10000000, -265, -229,-10000000, 5, -230, -257, -217, --10000000,-10000000,-10000000,-10000000,-10000000,-10000000, -231,-10000000, -232, -240, - -233, -217,-10000000, -245,-10000000, 4,-10000000, -253,-10000000,-10000000, - -251,-10000000,-10000000, -6, -2, 2, 1,-10000000,-10000000,-10000000, - -15, -234,-10000000, -217,-10000000,-10000000, -235, -237,-10000000, -238, - -239, -242, -243,-10000000,-10000000,-10000000, -29,-10000000,-10000000,-10000000, - -16,-10000000, -250, -258,-10000000,-10000000 }; +-10000000, -26, -268,-10000000, -264, -228,-10000000, 9, -229, -257, + -214, -230,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000, -231,-10000000, + -232, -240, -233, -214,-10000000, -258,-10000000, 8,-10000000, -246, +-10000000,-10000000, -260,-10000000,-10000000, 2, -4, 0, 6, 5, +-10000000,-10000000,-10000000, -13, -234,-10000000, -214,-10000000, -235,-10000000, + -237, -238,-10000000, -239, -242, -243, -244,-10000000,-10000000,-10000000, +-10000000, -3,-10000000,-10000000,-10000000, -14,-10000000, -251, -253,-10000000, +-10000000 }; static CONST TclDatetabelem TclDatepgo[]={ - 0, 50, 44, 62, 41, 60, 59, 58, 57, 56, - 55, 54, 53, 51 }; + 0, 49, 46, 66, 22, 65, 64, 63, 62, 60, + 59, 58, 57, 56, 55 }; static CONST TclDatetabelem TclDater1[]={ 0, 5, 5, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 8, 8, 8, 10, 10, - 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 12, 12, 12, 11, 11, 11, 11, - 11, 3, 3, 1, 1, 1, 2, 2, 13, 4, - 4 }; + 6, 7, 7, 7, 7, 7, 8, 8, 8, 10, + 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 12, 12, 12, 13, 11, 11, + 11, 11, 11, 3, 3, 1, 1, 1, 2, 2, + 14, 4, 4 }; static CONST TclDatetabelem TclDater2[]={ - 0, 0, 4, 3, 3, 3, 3, 3, 3, 2, - 5, 9, 11, 13, 15, 5, 3, 3, 3, 5, - 5, 7, 5, 7, 11, 3, 11, 11, 5, 9, - 5, 3, 7, 7, 15, 5, 9, 7, 5, 7, - 5, 3, 3, 3, 3, 3, 3, 1, 3, 1, - 3 }; + 0, 0, 4, 3, 3, 3, 3, 3, 3, 3, + 2, 5, 9, 11, 13, 15, 5, 3, 3, 3, + 5, 5, 7, 5, 7, 11, 3, 11, 11, 5, + 9, 5, 3, 7, 7, 15, 5, 9, 9, 7, + 5, 7, 5, 3, 3, 3, 3, 3, 3, 1, + 3, 1, 3 }; static CONST TclDatetabelem TclDatechk[]={ -10000000, -5, -6, -7, -8, -9, -10, -11, -12, -13, - 267, 268, 259, 271, 263, 269, 258, -3, 273, -1, - 45, 43, 265, 272, 264, 261, 58, 258, 47, 45, - 263, -1, 270, 268, 271, 267, 44, 267, 258, -1, - 267, -2, 257, 267, 267, 263, 267, 267, -2, 271, - 267, 44, 258, -1, -1, -4, 45, 58, 261, 47, - 45, 45, 58, 267, -2, 267, 267, 267, 267, 267, - 267, -4, 45, 58, 267, 267 }; + -14, 268, 269, 259, 272, 263, 270, 258, -3, 274, + -1, 265, 45, 43, 266, 273, 264, 261, 58, 258, + 47, 45, 263, -1, 271, 269, 272, 268, 44, 268, + 258, -1, 268, -2, 257, 268, 268, 268, 263, 268, + 268, -2, 272, 268, 44, 258, -1, -1, 46, -4, + 45, 58, 261, 47, 45, 45, 58, 268, -2, 268, + 268, 268, 268, 268, 268, 268, -4, 45, 58, 268, + 268 }; static CONST TclDatetabelem TclDatedef[]={ 1, -2, 2, 3, 4, 5, 6, 7, 8, 9, - 48, 16, 17, 25, 0, 31, 18, 0, 0, 47, - 41, 42, 43, 44, 45, 10, 0, 20, 0, 0, - 30, 47, 15, 0, 35, 28, 19, 0, 22, 38, - 0, 40, 46, 49, 23, 0, 0, 32, 37, 33, - 0, 0, 21, 47, 39, 11, 0, 0, 50, 0, - 0, 0, 0, 29, 36, 12, 49, 24, 26, 27, - 0, 13, 0, 0, 14, 34 }; + 10, 50, 17, 18, 26, 0, 32, 19, 0, 0, + 49, 0, 43, 44, 45, 46, 47, 11, 0, 21, + 0, 0, 31, 49, 16, 0, 36, 29, 20, 0, + 23, 40, 0, 42, 48, 0, 51, 24, 0, 0, + 33, 39, 34, 0, 0, 22, 49, 41, 0, 12, + 0, 0, 52, 0, 0, 0, 0, 30, 38, 37, + 13, 51, 25, 27, 28, 0, 14, 0, 0, 15, + 35 }; typedef struct #ifdef __cplusplus TclDatetoktype @@ -982,15 +984,16 @@ TclDatetoktype TclDatetoks[] = "tMINUTE_UNIT", 262, "tMONTH", 263, "tMONTH_UNIT", 264, - "tSEC_UNIT", 265, - "tSNUMBER", 266, - "tUNUMBER", 267, - "tZONE", 268, - "tEPOCH", 269, - "tDST", 270, - "tISOBASE", 271, - "tDAY_UNIT", 272, - "tNEXT", 273, + "tSTARDATE", 265, + "tSEC_UNIT", 266, + "tSNUMBER", 267, + "tUNUMBER", 268, + "tZONE", 269, + "tEPOCH", 270, + "tDST", 271, + "tISOBASE", 272, + "tDAY_UNIT", 273, + "tNEXT", 274, "-unknown-", -1 /* ends search */ }; @@ -1005,6 +1008,7 @@ char * TclDatereds[] = "item : day", "item : relspec", "item : iso", + "item : trek", "item : number", "time : tUNUMBER tMERIDIAN", "time : tUNUMBER ':' tUNUMBER o_merid", @@ -1032,6 +1036,7 @@ char * TclDatereds[] = "iso : tISOBASE tZONE tISOBASE", "iso : tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER", "iso : tISOBASE tISOBASE", + "trek : tSTARDATE tUNUMBER '.' tUNUMBER", "relspec : sign tUNUMBER unit ago", "relspec : tUNUMBER unit ago", "relspec : tNEXT unit", @@ -1595,32 +1600,37 @@ case 8:{ TclDateHaveTime++; TclDateHaveDate++; } break; -case 10:{ +case 9:{ + TclDateHaveTime++; + TclDateHaveDate++; + TclDateHaveRel++; + } break; +case 11:{ TclDateHour = TclDatepvt[-1].Number; TclDateMinutes = 0; TclDateSeconds = 0; TclDateMeridian = TclDatepvt[-0].Meridian; } break; -case 11:{ +case 12:{ TclDateHour = TclDatepvt[-3].Number; TclDateMinutes = TclDatepvt[-1].Number; TclDateSeconds = 0; TclDateMeridian = TclDatepvt[-0].Meridian; } break; -case 12:{ +case 13:{ TclDateHour = TclDatepvt[-4].Number; TclDateMinutes = TclDatepvt[-2].Number; TclDateMeridian = MER24; TclDateDSTmode = DSToff; TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60); } break; -case 13:{ +case 14:{ TclDateHour = TclDatepvt[-5].Number; TclDateMinutes = TclDatepvt[-3].Number; TclDateSeconds = TclDatepvt[-1].Number; TclDateMeridian = TclDatepvt[-0].Meridian; } break; -case 14:{ +case 15:{ TclDateHour = TclDatepvt[-6].Number; TclDateMinutes = TclDatepvt[-4].Number; TclDateSeconds = TclDatepvt[-2].Number; @@ -1628,86 +1638,86 @@ case 14:{ TclDateDSTmode = DSToff; TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60); } break; -case 15:{ +case 16:{ TclDateTimezone = TclDatepvt[-1].Number; TclDateDSTmode = DSTon; } break; -case 16:{ +case 17:{ TclDateTimezone = TclDatepvt[-0].Number; TclDateDSTmode = DSToff; } break; -case 17:{ +case 18:{ TclDateTimezone = TclDatepvt[-0].Number; TclDateDSTmode = DSTon; } break; -case 18:{ +case 19:{ TclDateDayOrdinal = 1; TclDateDayNumber = TclDatepvt[-0].Number; } break; -case 19:{ +case 20:{ TclDateDayOrdinal = 1; TclDateDayNumber = TclDatepvt[-1].Number; } break; -case 20:{ +case 21:{ TclDateDayOrdinal = TclDatepvt[-1].Number; TclDateDayNumber = TclDatepvt[-0].Number; } break; -case 21:{ +case 22:{ TclDateDayOrdinal = TclDatepvt[-2].Number * TclDatepvt[-1].Number; TclDateDayNumber = TclDatepvt[-0].Number; } break; -case 22:{ +case 23:{ TclDateDayOrdinal = 2; TclDateDayNumber = TclDatepvt[-0].Number; } break; -case 23:{ +case 24:{ TclDateMonth = TclDatepvt[-2].Number; TclDateDay = TclDatepvt[-0].Number; } break; -case 24:{ +case 25:{ TclDateMonth = TclDatepvt[-4].Number; TclDateDay = TclDatepvt[-2].Number; TclDateYear = TclDatepvt[-0].Number; } break; -case 25:{ +case 26:{ TclDateYear = TclDatepvt[-0].Number / 10000; TclDateMonth = (TclDatepvt[-0].Number % 10000)/100; TclDateDay = TclDatepvt[-0].Number % 100; } break; -case 26:{ +case 27:{ TclDateDay = TclDatepvt[-4].Number; TclDateMonth = TclDatepvt[-2].Number; TclDateYear = TclDatepvt[-0].Number; } break; -case 27:{ +case 28:{ TclDateMonth = TclDatepvt[-2].Number; TclDateDay = TclDatepvt[-0].Number; TclDateYear = TclDatepvt[-4].Number; } break; -case 28:{ +case 29:{ TclDateMonth = TclDatepvt[-1].Number; TclDateDay = TclDatepvt[-0].Number; } break; -case 29:{ +case 30:{ TclDateMonth = TclDatepvt[-3].Number; TclDateDay = TclDatepvt[-2].Number; TclDateYear = TclDatepvt[-0].Number; } break; -case 30:{ +case 31:{ TclDateMonth = TclDatepvt[-0].Number; TclDateDay = TclDatepvt[-1].Number; } break; -case 31:{ +case 32:{ TclDateMonth = 1; TclDateDay = 1; TclDateYear = EPOCH; } break; -case 32:{ +case 33:{ TclDateMonth = TclDatepvt[-1].Number; TclDateDay = TclDatepvt[-2].Number; TclDateYear = TclDatepvt[-0].Number; } break; -case 33:{ +case 34:{ if (TclDatepvt[-1].Number != HOUR(- 7)) YYABORT; TclDateYear = TclDatepvt[-2].Number / 10000; TclDateMonth = (TclDatepvt[-2].Number % 10000)/100; @@ -1716,7 +1726,7 @@ case 33:{ TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100; TclDateSeconds = TclDatepvt[-0].Number % 100; } break; -case 34:{ +case 35:{ if (TclDatepvt[-5].Number != HOUR(- 7)) YYABORT; TclDateYear = TclDatepvt[-6].Number / 10000; TclDateMonth = (TclDatepvt[-6].Number % 10000)/100; @@ -1725,7 +1735,7 @@ case 34:{ TclDateMinutes = TclDatepvt[-2].Number; TclDateSeconds = TclDatepvt[-0].Number; } break; -case 35:{ +case 36:{ TclDateYear = TclDatepvt[-1].Number / 10000; TclDateMonth = (TclDatepvt[-1].Number % 10000)/100; TclDateDay = TclDatepvt[-1].Number % 100; @@ -1733,19 +1743,30 @@ case 35:{ TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100; TclDateSeconds = TclDatepvt[-0].Number % 100; } break; -case 36:{ *TclDateRelPointer += TclDatepvt[-3].Number * TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 37:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 38:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break; -case 39:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 40:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; -case 41:{ TclDateval.Number = -1; } break; -case 42:{ TclDateval.Number = 1; } break; -case 43:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break; -case 44:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break; -case 45:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break; -case 46:{ TclDateval.Number = -1; } break; -case 47:{ TclDateval.Number = 1; } break; -case 48:{ +case 37:{ + /* + * Offset computed year by -377 so that the returned years will + * be in a range accessible with a 32 bit clock seconds value + */ + TclDateYear = TclDatepvt[-2].Number/1000 + 2323 - 377; + TclDateDay = 1; + TclDateMonth = 1; + TclDateRelDay += ((TclDatepvt[-2].Number%1000)*(365 + IsLeapYear(TclDateYear)))/1000; + TclDateRelSeconds += TclDatepvt[-0].Number * 144 * 60; + } break; +case 38:{ *TclDateRelPointer += TclDatepvt[-3].Number * TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; +case 39:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; +case 40:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break; +case 41:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; +case 42:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break; +case 43:{ TclDateval.Number = -1; } break; +case 44:{ TclDateval.Number = 1; } break; +case 45:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break; +case 46:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break; +case 47:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break; +case 48:{ TclDateval.Number = -1; } break; +case 49:{ TclDateval.Number = 1; } break; +case 50:{ if (TclDateHaveTime && TclDateHaveDate && !TclDateHaveRel) { TclDateYear = TclDatepvt[-0].Number; } else { @@ -1761,10 +1782,10 @@ case 48:{ TclDateMeridian = MER24; } } break; -case 49:{ +case 51:{ TclDateval.Meridian = MER24; } break; -case 50:{ +case 52:{ TclDateval.Meridian = TclDatepvt[-0].Meridian; } break; } diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y index ea66fd7..7e6e01e 100644 --- a/generic/tclGetDate.y +++ b/generic/tclGetDate.y @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclGetDate.y,v 1.12 2000/01/12 23:35:52 ericm Exp $ + * RCS: @(#) $Id: tclGetDate.y,v 1.13 2000/01/14 22:15:51 ericm Exp $ */ %{ @@ -54,7 +54,7 @@ #define HOUR(x) ((int) (60 * x)) #define SECSPERDAY (24L * 60L * 60L) - +#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) /* * An entry in the lexical lookup table. @@ -138,11 +138,12 @@ yyparse _ANSI_ARGS_((void)); } %token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT -%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tEPOCH tDST tISOBASE tDAY_UNIT tNEXT +%token tSTARDATE tSEC_UNIT tSNUMBER tUNUMBER tZONE tEPOCH tDST tISOBASE +%token tDAY_UNIT tNEXT %type tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT tDST %type tSEC_UNIT tSNUMBER tUNUMBER tZONE tISOBASE tDAY_UNIT -%type unit ago sign tNEXT +%type unit ago sign tNEXT tSTARDATE %type tMERIDIAN o_merid %% @@ -170,6 +171,11 @@ item : time { yyHaveTime++; yyHaveDate++; } + | trek { + yyHaveTime++; + yyHaveDate++; + yyHaveRel++; + } | number ; @@ -321,6 +327,19 @@ iso : tISOBASE tZONE tISOBASE { } ; +trek : tSTARDATE tUNUMBER '.' tUNUMBER { + /* + * Offset computed year by -377 so that the returned years will + * be in a range accessible with a 32 bit clock seconds value + */ + yyYear = $2/1000 + 2323 - 377; + yyDay = 1; + yyMonth = 1; + yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000; + yyRelSeconds += $4 * 144 * 60; + } + ; + relspec : sign tUNUMBER unit ago { *yyRelPointer += $1 * $2 * $3 * $4; } | tUNUMBER unit ago { *yyRelPointer += $1 * $2 * $3; } | tNEXT unit { *yyRelPointer += $2; } @@ -442,6 +461,7 @@ static TABLE OtherTable[] = { #endif { "ago", tAGO, 1 }, { "epoch", tEPOCH, 0 }, + { "stardate", tSTARDATE, 0}, { NULL } }; @@ -636,8 +656,7 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr) * But, every year divisible by 100 is not a leap year. * But, every year divisible by 400 is a leap year after all. */ - DaysInMonth[1] = (Year % 4 == 0) && (Year % 100 != 0 || Year % 400 == 0) - ? 29 : 28; + DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28; /* Check the inputs for validity */ if (Month < 1 || Month > 12 @@ -652,12 +671,10 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr) Julian += DaysInMonth[i]; if (Year >= EPOCH) { for (i = EPOCH; i < Year; i++) - Julian += 365 + (((i % 4) == 0) && - (((i % 100) != 0) || ((i % 400) == 0))); + Julian += 365 + IsLeapYear(i); } else { for (i = Year; i < EPOCH; i++) - Julian -= 365 + (((i % 4) == 0) && - (((i % 100) != 0) || ((i % 400) == 0))); + Julian -= 365 + IsLeapYear(i); } Julian *= SECSPERDAY; diff --git a/tests/clock.test b/tests/clock.test index a947a42..74a32b4 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -10,7 +10,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: clock.test,v 1.8 2000/01/13 00:12:33 ericm Exp $ +# RCS: @(#) $Id: clock.test,v 1.9 2000/01/14 22:15:51 ericm Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest @@ -221,11 +221,11 @@ test clock-4.24 {clock scan, number:number:number-timezone} { -format {%b %d, %Y %H:%M:%S} -gmt true } "Dec 31, 1999 08:00:30" test clock-4.25 {clock scan, DST for days} { - clock scan "tomorrow" -base 941353200 -} 941443200 + clock scan "tomorrow" -base [clock scan "19991031 00:00:00"] +} [clock scan "19991101 00:00:00"] test clock-4.26 {clock scan, DST for days} { - clock scan "yesterday" -base 941443200 -} 941353200 + clock scan "yesterday" -base [clock scan "19991101 00:00:00"] +} [clock scan "19991031 00:00:00"] test clock-4.27 {clock scan, day} knownBug { clock format [clock scan "Monday" -gmt true -base 946627200] \ -format {%b %d, %Y %H:%M:%S} -gmt true diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index c1a9161..9990aad 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -9,11 +9,13 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixTime.c,v 1.6 1999/07/22 01:26:19 redman Exp $ + * RCS: @(#) $Id: tclUnixTime.c,v 1.7 2000/01/14 22:15:52 ericm Exp $ */ #include "tclInt.h" #include "tclPort.h" +#define TM_YEAR_BASE 1900 +#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) /* *----------------------------------------------------------------------------- @@ -295,5 +297,14 @@ TclpStrftime(s, maxsize, format, t) CONST char *format; CONST struct tm *t; { + if (format[0] == '%' && format[1] == 'Q') { + /* Format as a stardate */ + sprintf(s, "Stardate %2d%03d.%01d", + (((t->tm_year + TM_YEAR_BASE) + 377) - 2323), + (((t->tm_yday + 1) * 1000) / + (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))), + (((t->tm_hour * 60) + t->tm_min)/144)); + return(strlen(s)); + } return strftime(s, maxsize, format, t); } -- cgit v0.12