| ︙ | | |
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
|
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
|
-
+
-
+
|
Tcl_DictObjPut(NULL, dict, lit[LIT_TZNAME], fields.tzName);
Tcl_DecrRefCount(fields.tzName);
Tcl_DictObjPut(NULL, dict, lit[LIT_TZOFFSET],
Tcl_NewWideIntObj(fields.tzOffset));
Tcl_DictObjPut(NULL, dict, lit[LIT_JULIANDAY],
Tcl_NewWideIntObj(fields.julianDay));
Tcl_DictObjPut(NULL, dict, lit[LIT_GREGORIAN],
Tcl_NewWideIntObj(fields.gregorian));
Tcl_NewWideIntObj(!(fields.flags & CLF_BGREG)));
Tcl_DictObjPut(NULL, dict, lit[LIT_ERA],
lit[fields.isBce ? LIT_BCE : LIT_CE]);
lit[(fields.flags & CLF_BCE) ? LIT_BCE : LIT_CE]);
Tcl_DictObjPut(NULL, dict, lit[LIT_YEAR],
Tcl_NewWideIntObj(fields.year));
Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFYEAR],
Tcl_NewWideIntObj(fields.dayOfYear));
Tcl_DictObjPut(NULL, dict, lit[LIT_MONTH],
Tcl_NewWideIntObj(fields.month));
Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFMONTH],
|
| ︙ | | |
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
|
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
|
+
-
+
+
+
+
|
|| FetchIntField(interp, dict, lit[LIT_MONTH], &fields.month)
!= TCL_OK
|| FetchIntField(interp, dict, lit[LIT_DAYOFMONTH],
&fields.dayOfMonth) != TCL_OK
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
return TCL_ERROR;
}
if (isBce) {
fields.isBce = isBce;
fields.flags |= CLF_BCE;
} else {
fields.flags &= ~CLF_BCE;
}
/*
* Get Julian day.
*/
GetJulianDayFromEraYearMonthDay(&fields, changeover);
|
| ︙ | | |
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
|
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
|
+
-
+
+
+
+
|
|| FetchIntField(interp, dict, lit[LIT_ISO8601WEEK],
&fields.iso8601Week) != TCL_OK
|| FetchIntField(interp, dict, lit[LIT_DAYOFWEEK],
&fields.dayOfWeek) != TCL_OK
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
return TCL_ERROR;
}
if (isBce) {
fields.isBce = isBce;
fields.flags |= CLF_BCE;
} else {
fields.flags &= ~CLF_BCE;
}
/*
* Get Julian day.
*/
GetJulianDayFromEraYearWeekDay(&fields, changeover);
|
| ︙ | | |
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
|
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
|
-
+
|
return TCL_ERROR;
}
/*
* Fill in the date in 'fields' and use it to derive Julian Day.
*/
fields->isBce = 0;
fields->flags &= ~CLF_BCE;
fields->year = timeVal->tm_year + 1900;
fields->month = timeVal->tm_mon + 1;
fields->dayOfMonth = timeVal->tm_mday;
GetJulianDayFromEraYearMonthDay(fields, changeover);
/*
* Convert that value to seconds.
|
| ︙ | | |
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
|
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
|
-
+
-
+
|
/*
* Find the given date, minus three days, plus one year. That date's
* iso8601 year is an upper bound on the ISO8601 year of the given date.
*/
temp.julianDay = fields->julianDay - 3;
GetGregorianEraYearDay(&temp, changeover);
if (temp.isBce) {
if (temp.flags & CLF_BCE) {
temp.iso8601Year = temp.year - 1;
} else {
temp.iso8601Year = temp.year + 1;
}
temp.iso8601Week = 1;
temp.dayOfWeek = 1;
GetJulianDayFromEraYearWeekDay(&temp, changeover);
/*
* temp.julianDay is now the start of an ISO8601 year, either the one
* corresponding to the given date, or the one after. If we guessed high,
* move one year earlier
*/
if (fields->julianDay < temp.julianDay) {
if (temp.isBce) {
if (temp.flags & CLF_BCE) {
temp.iso8601Year += 1;
} else {
temp.iso8601Year -= 1;
}
GetJulianDayFromEraYearWeekDay(&temp, changeover);
}
|
| ︙ | | |
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
|
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
|
-
+
|
int n;
if (jday >= changeover) {
/*
* Gregorian calendar.
*/
fields->gregorian = 1;
fields->flags &= ~CLF_BGREG;
year = 1;
/*
* n = Number of 400-year cycles since 1 January, 1 CE in the
* proleptic Gregorian calendar. day = remaining days.
*/
|
| ︙ | | |
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
|
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
|
-
+
|
}
year += 100 * n;
} else {
/*
* Julian calendar.
*/
fields->gregorian = 0;
fields->flags |= CLF_BGREG;
year = 1;
day = jday - JDAY_1_JAN_1_CE_JULIAN;
}
/*
* n = number of 4-year cycles; days = remaining days.
*/
|
| ︙ | | |
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
|
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
|
-
+
-
+
|
year += n;
/*
* store era/year/day back into fields.
*/
if (year <= 0) {
fields->isBce = 1;
fields->flags |= CLF_BCE;
fields->year = 1 - year;
} else {
fields->isBce = 0;
fields->flags &= ~CLF_BCE;
fields->year = year;
}
fields->dayOfYear = (int)day + 1;
}
/*
*----------------------------------------------------------------------
|
| ︙ | | |
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
|
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
|
-
+
+
+
+
+
+
|
firstWeek.tzName = NULL;
/*
* Find January 4 in the ISO8601 year, which will always be in week 1.
*/
firstWeek.isBce = fields->isBce;
firstWeek.flags = (fields->flags & CLF_BCE);
firstWeek.year = fields->iso8601Year;
firstWeek.month = 1;
firstWeek.dayOfMonth = 4;
GetJulianDayFromEraYearMonthDay(&firstWeek, changeover);
/*
* Find Monday of week 1.
*/
firstMonday = WeekdayOnOrBefore(1, firstWeek.julianDay);
/*
* Advance to the given week and day.
*/
fields->julianDay = firstMonday + 7 * (fields->iso8601Week - 1)
+ fields->dayOfWeek - 1;
if (fields->julianDay >= changeover) {
fields->flags &= ~CLF_BGREG;
} else {
fields->flags |= CLF_BGREG;
}
}
/*
*----------------------------------------------------------------------
*
* GetJulianDayFromEraYearMonthDay --
*
|
| ︙ | | |
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
|
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
|
-
+
|
GetJulianDayFromEraYearMonthDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
Tcl_WideInt ym1, ym1o4, ym1o100, ym1o400;
int year, month, mm1, q, r;
if (fields->isBce) {
if (fields->flags & CLF_BCE) {
year = 1 - fields->year;
} else {
year = fields->year;
}
/*
* Reduce month modulo 12.
|
| ︙ | | |
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
|
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
|
-
+
-
+
-
+
|
month = r + 1;
ym1 = year - 1;
/*
* Adjust the year after reducing the month.
*/
fields->gregorian = 1;
fields->flags &= ~CLF_BGREG;
if (year < 1) {
fields->isBce = 1;
fields->flags |= CLF_BCE;
fields->year = 1 - year;
} else {
fields->isBce = 0;
fields->flags &= ~CLF_BCE;
fields->year = year;
}
/*
* Try an initial conversion in the Gregorian calendar.
*/
|
| ︙ | | |
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
|
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
|
-
+
-
+
|
/*
* If the resulting date is before the Gregorian changeover, convert in
* the Julian calendar instead.
*/
if (fields->julianDay < changeover) {
fields->gregorian = 0;
fields->flags |= CLF_BGREG;
fields->julianDay = JDAY_1_JAN_1_CE_JULIAN - 1
+ fields->dayOfMonth
+ daysInPriorMonths[year%4 == 0][month - 1]
+ (365 * ym1)
+ (ONE_YEAR * ym1)
+ ym1o4;
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | | |
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
|
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
|
-
+
-
+
-
+
-
+
-
+
-
+
-
+
|
TclGetJulianDayFromEraYearDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
Tcl_WideInt year, ym1;
/* Get absolute year number from the civil year */
if (fields->isBce) {
if (fields->flags & CLF_BCE) {
year = 1 - fields->year;
} else {
year = fields->year;
}
ym1 = year - 1;
/* Try the Gregorian calendar first. */
fields->gregorian = 1;
fields->flags &= ~CLF_BGREG;
fields->julianDay =
1721425
JDAY_1_JAN_1_CE_GREGORIAN - 1
+ fields->dayOfYear
+ (365 * ym1)
+ (ONE_YEAR * 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->flags |= CLF_BGREG;
fields->julianDay =
1721423
JDAY_1_JAN_1_CE_JULIAN - 1
+ fields->dayOfYear
+ (365 * ym1)
+ (ONE_YEAR * ym1)
+ (ym1 / 4);
}
}
/*
*----------------------------------------------------------------------
*
* TclIsGregorianLeapYear --
|
| ︙ | | |
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
|
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
|
-
+
-
+
+
|
int
TclIsGregorianLeapYear(
TclDateFields *fields) /* Date to test */
{
Tcl_WideInt year = fields->year;
if (fields->isBce) {
if (fields->flags & CLF_BCE) {
year = 1 - year;
}
if (year % 4 != 0) {
return 0;
} else if (!(fields->gregorian)) {
} else if (fields->flags & CLF_BGREG) {
/* Before Gregorian leap year didn't follow y/100 and y/400 logic. */
return 1;
} else if (year % 400 == 0) {
return 1;
} else if (year % 100 == 0) {
return 0;
} else {
return 1;
|
| ︙ | | |
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
|
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds));
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* ClockAssembleJulianDay --
*
* Assembles julianDay using year, month, etc. Thereby it'd also update
* gregorian flag.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
ClockAssembleJulianDay(
DateInfo *info) /* Clock scan info structure */
{
/* Assemble julianDay (and also gregorian flag) */
if (info->flags & CLF_ISO8601WEEK) {
GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
} else if (!(info->flags & CLF_DAYOFYEAR) /* no day of year */
|| (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */
== (CLF_DAYOFMONTH|CLF_MONTH)) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
} else {
TclGetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
}
info->flags |= CLF_ASSEMBLE_SECONDS;
}
/*----------------------------------------------------------------------
*
* ClockScanCommit --
*
* Converts date info structure into UTC seconds.
*
* Results:
* Returns a standard Tcl result.
*
|
| ︙ | | |
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
|
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
|
-
-
+
-
-
-
-
-
-
-
-
|
if (ClockValidDate(info, opts, CLF_VALIDATE_S1) != TCL_OK) {
return TCL_ERROR;
}
}
/* If needed assemble julianDay using year, month, etc. */
if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
if (info->flags & CLF_ISO8601WEEK) {
GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
ClockAssembleJulianDay(info);
} else if (!(info->flags & CLF_DAYOFYEAR) /* no day of year */
|| (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */
== (CLF_DAYOFMONTH|CLF_MONTH)) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
} else {
TclGetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
}
info->flags |= CLF_ASSEMBLE_SECONDS;
info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
/* some overflow checks */
if (info->flags & CLF_JULIANDAY) {
double curJDN = (double)yydate.julianDay
+ ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY;
|
| ︙ | | |
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
|
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
|
+
+
+
+
+
+
+
+
|
if (info->flags & CLF_MONTH) {
if (yyMonth < 1 || yyMonth > 12) {
errMsg = "invalid month";
errCode = "month";
goto error;
}
}
/* To check day in leap year correct, validation may need gregorian flag,
* so assemble julianDay and gregorian flag from date tokens. */
if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
ClockAssembleJulianDay(info);
info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
/* day of month */
if (info->flags & (CLF_DAYOFMONTH|CLF_DAYOFWEEK)) {
if (yyDay < 1 || yyDay > 31) {
errMsg = "invalid day";
errCode = "day";
goto error;
}
|
| ︙ | | |
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
|
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
|
-
+
|
if (info->flags & CLF_YEAR) {
if (yyYear < 100) {
if (yyYear >= dataPtr->yearOfCenturySwitch) {
yyYear -= 100;
}
yyYear += dataPtr->currentYearCentury;
}
yydate.isBce = 0;
yydate.flags &= ~CLF_BCE;
info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
}
/*
* If the caller supplied a time zone in the string, make it into a time
* zone indicator of +-hhmm and setup this time zone.
*/
|
| ︙ | | |
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
|
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
|
-
+
|
/* if needed assemble julianDay now */
if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
}
yydate.isBce = 0;
yydate.flags &= ~CLF_BCE;
yydate.julianDay = WeekdayOnOrBefore(yyDayOfWeek, yydate.julianDay + 6)
+ 7 * yyDayOrdinal;
if (yyDayOrdinal > 0) {
yydate.julianDay -= 7;
}
info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
}
|
| ︙ | | |