@@ -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
@@ -588,30 +610,21 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
588
610
589
611
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
590
612
591
- UCalendar* icuCalendar = icuLib.ucalOpen (
592
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
613
+ auto icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
593
614
594
615
if (!icuCalendar)
595
616
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
596
617
597
618
icuLib.ucalSetMillis (icuCalendar, timeStampToIcuDate (timeStampTz.utc_timestamp ), &icuErrorCode);
598
619
599
620
if (U_FAILURE (icuErrorCode))
600
- {
601
- icuLib.ucalClose (icuCalendar);
602
621
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_setMillis." );
603
- }
604
622
605
623
displacement = (icuLib.ucalGet (icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
606
624
icuLib.ucalGet (icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
607
625
608
626
if (U_FAILURE (icuErrorCode))
609
- {
610
- icuLib.ucalClose (icuCalendar);
611
627
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_get." );
612
- }
613
-
614
- icuLib.ucalClose (icuCalendar);
615
628
}
616
629
617
630
*offset = displacement;
@@ -683,8 +696,7 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
683
696
684
697
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
685
698
686
- UCalendar* icuCalendar = icuLib.ucalOpen (
687
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
699
+ auto icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
688
700
689
701
if (!icuCalendar)
690
702
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
@@ -696,21 +708,13 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
696
708
times.tm_hour , times.tm_min , times.tm_sec , &icuErrorCode);
697
709
698
710
if (U_FAILURE (icuErrorCode))
699
- {
700
- icuLib.ucalClose (icuCalendar);
701
711
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_setDateTime." );
702
- }
703
712
704
713
displacement = (icuLib.ucalGet (icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
705
714
icuLib.ucalGet (icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
706
715
707
716
if (U_FAILURE (icuErrorCode))
708
- {
709
- icuLib.ucalClose (icuCalendar);
710
717
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_get." );
711
- }
712
-
713
- icuLib.ucalClose (icuCalendar);
714
718
}
715
719
716
720
const auto ticks = TimeStamp::timeStampToTicks (timeStampTz.utc_timestamp ) -
@@ -752,30 +756,21 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
752
756
#endif
753
757
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
754
758
755
- UCalendar* icuCalendar = icuLib.ucalOpen (
756
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
759
+ auto icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
757
760
758
761
if (!icuCalendar)
759
762
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
760
763
761
764
icuLib.ucalSetMillis (icuCalendar, timeStampToIcuDate (timeStampTz.utc_timestamp ), &icuErrorCode);
762
765
763
766
if (U_FAILURE (icuErrorCode))
764
- {
765
- icuLib.ucalClose (icuCalendar);
766
767
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_setMillis." );
767
- }
768
768
769
769
displacement = (icuLib.ucalGet (icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
770
770
icuLib.ucalGet (icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
771
771
772
772
if (U_FAILURE (icuErrorCode))
773
- {
774
- icuLib.ucalClose (icuCalendar);
775
773
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_get." );
776
- }
777
-
778
- icuLib.ucalClose (icuCalendar);
779
774
}
780
775
catch (const Exception&)
781
776
{
@@ -1044,12 +1039,11 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::dateToTimeStampTz(const ISC_DATE& date, Callbacks
1044
1039
TimeZoneRuleIterator::TimeZoneRuleIterator (USHORT aId, const ISC_TIMESTAMP_TZ& aFrom, const ISC_TIMESTAMP_TZ& aTo)
1045
1040
: id(aId),
1046
1041
icuLib(Jrd::UnicodeUtil::getConversionICU()),
1047
- toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp))
1042
+ toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp)),
1043
+ icuCalendar(getDesc(aId)->getCalendar(icuLib))
1048
1044
{
1049
1045
UErrorCode icuErrorCode = U_ZERO_ERROR;
1050
1046
1051
- icuCalendar = icuLib.ucalOpen (getDesc (id)->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
1052
-
1053
1047
if (!icuCalendar)
1054
1048
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
1055
1049
@@ -1086,11 +1080,6 @@ TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& a
1086
1080
startTicks = TimeStamp::timeStampToTicks (TimeZoneUtil::icuDateToTimeStamp (icuDate));
1087
1081
}
1088
1082
1089
- TimeZoneRuleIterator::~TimeZoneRuleIterator ()
1090
- {
1091
- icuLib.ucalClose (icuCalendar);
1092
- }
1093
-
1094
1083
bool TimeZoneRuleIterator::next ()
1095
1084
{
1096
1085
if (startTicks > toTicks)
0 commit comments