@@ -45,10 +45,20 @@ namespace
45
45
public:
46
46
TimeZoneDesc (MemoryPool& pool)
47
47
: asciiName(pool),
48
- unicodeName (pool)
48
+ unicodeName (pool),
49
+ icuCachedCalendar(nullptr )
49
50
{
50
51
}
51
52
53
+ ~TimeZoneDesc ()
54
+ {
55
+ if (const auto calendar = icuCachedCalendar.exchange (nullptr ))
56
+ {
57
+ auto & icuLib = Jrd::UnicodeUtil::getConversionICU ();
58
+ icuLib.ucalClose (calendar);
59
+ }
60
+ }
61
+
52
62
public:
53
63
void setName (const char * name)
54
64
{
@@ -70,9 +80,21 @@ namespace
70
80
return unicodeName.begin ();
71
81
}
72
82
83
+ IcuCalendarWrapper getCalendar (const Jrd::UnicodeUtil::ConversionICU& icuLib, UErrorCode* err = nullptr ) const
84
+ {
85
+ auto calendar = icuCachedCalendar.exchange (nullptr );
86
+ UErrorCode internalErr = U_ZERO_ERROR;
87
+
88
+ if (!calendar)
89
+ calendar = icuLib.ucalOpen (getUnicodeName (), -1 , nullptr , UCAL_GREGORIAN, (err ? err : &internalErr));
90
+
91
+ return IcuCalendarWrapper (calendar, &icuCachedCalendar);
92
+ }
93
+
73
94
private:
74
95
string asciiName;
75
96
Array<UChar> unicodeName;
97
+ mutable std::atomic<UCalendar*> icuCachedCalendar;
76
98
};
77
99
}
78
100
@@ -594,30 +616,21 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
594
616
595
617
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
596
618
597
- UCalendar* icuCalendar = icuLib.ucalOpen (
598
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
619
+ auto icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
599
620
600
621
if (!icuCalendar)
601
622
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
602
623
603
624
icuLib.ucalSetMillis (icuCalendar, timeStampToIcuDate (timeStampTz.utc_timestamp ), &icuErrorCode);
604
625
605
626
if (U_FAILURE (icuErrorCode))
606
- {
607
- icuLib.ucalClose (icuCalendar);
608
627
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_setMillis." );
609
- }
610
628
611
629
displacement = (icuLib.ucalGet (icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
612
630
icuLib.ucalGet (icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
613
631
614
632
if (U_FAILURE (icuErrorCode))
615
- {
616
- icuLib.ucalClose (icuCalendar);
617
633
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_get." );
618
- }
619
-
620
- icuLib.ucalClose (icuCalendar);
621
634
}
622
635
623
636
*offset = displacement;
@@ -689,8 +702,7 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
689
702
690
703
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
691
704
692
- UCalendar* icuCalendar = icuLib.ucalOpen (
693
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
705
+ auto icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
694
706
695
707
if (!icuCalendar)
696
708
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
@@ -702,21 +714,13 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
702
714
times.tm_hour , times.tm_min , times.tm_sec , &icuErrorCode);
703
715
704
716
if (U_FAILURE (icuErrorCode))
705
- {
706
- icuLib.ucalClose (icuCalendar);
707
717
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_setDateTime." );
708
- }
709
718
710
719
displacement = (icuLib.ucalGet (icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
711
720
icuLib.ucalGet (icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
712
721
713
722
if (U_FAILURE (icuErrorCode))
714
- {
715
- icuLib.ucalClose (icuCalendar);
716
723
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_get." );
717
- }
718
-
719
- icuLib.ucalClose (icuCalendar);
720
724
}
721
725
722
726
const auto ticks = TimeStamp::timeStampToTicks (timeStampTz.utc_timestamp ) -
@@ -758,30 +762,21 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
758
762
#endif
759
763
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
760
764
761
- UCalendar* icuCalendar = icuLib.ucalOpen (
762
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
765
+ auto icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
763
766
764
767
if (!icuCalendar)
765
768
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
766
769
767
770
icuLib.ucalSetMillis (icuCalendar, timeStampToIcuDate (timeStampTz.utc_timestamp ), &icuErrorCode);
768
771
769
772
if (U_FAILURE (icuErrorCode))
770
- {
771
- icuLib.ucalClose (icuCalendar);
772
773
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_setMillis." );
773
- }
774
774
775
775
displacement = (icuLib.ucalGet (icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
776
776
icuLib.ucalGet (icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
777
777
778
778
if (U_FAILURE (icuErrorCode))
779
- {
780
- icuLib.ucalClose (icuCalendar);
781
779
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_get." );
782
- }
783
-
784
- icuLib.ucalClose (icuCalendar);
785
780
}
786
781
catch (const Exception&)
787
782
{
@@ -1050,12 +1045,11 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::dateToTimeStampTz(const ISC_DATE& date, Callbacks
1050
1045
TimeZoneRuleIterator::TimeZoneRuleIterator (USHORT aId, const ISC_TIMESTAMP_TZ& aFrom, const ISC_TIMESTAMP_TZ& aTo)
1051
1046
: id(aId),
1052
1047
icuLib(Jrd::UnicodeUtil::getConversionICU()),
1053
- toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp))
1048
+ toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp)),
1049
+ icuCalendar(getDesc(aId)->getCalendar(icuLib))
1054
1050
{
1055
1051
UErrorCode icuErrorCode = U_ZERO_ERROR;
1056
1052
1057
- icuCalendar = icuLib.ucalOpen (getDesc (id)->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
1058
-
1059
1053
if (!icuCalendar)
1060
1054
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
1061
1055
@@ -1092,11 +1086,6 @@ TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& a
1092
1086
startTicks = TimeStamp::timeStampToTicks (TimeZoneUtil::icuDateToTimeStamp (icuDate));
1093
1087
}
1094
1088
1095
- TimeZoneRuleIterator::~TimeZoneRuleIterator ()
1096
- {
1097
- icuLib.ucalClose (icuCalendar);
1098
- }
1099
-
1100
1089
bool TimeZoneRuleIterator::next ()
1101
1090
{
1102
1091
if (startTicks > toTicks)
0 commit comments