36
36
#include " ../common/os/os_utils.h"
37
37
#include " unicode/ucal.h"
38
38
39
+ #include < atomic>
40
+
39
41
using namespace Firebird ;
40
42
41
43
namespace
@@ -45,8 +47,19 @@ namespace
45
47
public:
46
48
TimeZoneDesc (MemoryPool& pool)
47
49
: asciiName(pool),
48
- unicodeName (pool)
50
+ unicodeName (pool),
51
+ calendar(nullptr )
52
+ {
53
+ }
54
+
55
+ ~TimeZoneDesc ()
49
56
{
57
+ UCalendar* val = calendar.exchange (nullptr );
58
+ if (val)
59
+ {
60
+ auto & icuLib = Jrd::UnicodeUtil::getConversionICU ();
61
+ icuLib.ucalClose (val);
62
+ }
50
63
}
51
64
52
65
public:
@@ -70,9 +83,26 @@ namespace
70
83
return unicodeName.begin ();
71
84
}
72
85
86
+ UCalendar* getCalendar (const Jrd::UnicodeUtil::ConversionICU& icuLib, UErrorCode* err) const
87
+ {
88
+ UCalendar* val = calendar.load ();
89
+ if (!val)
90
+ {
91
+ val = icuLib.ucalOpen (getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, err);
92
+ if (!val)
93
+ return val;
94
+
95
+ UCalendar* old = calendar.exchange (val);
96
+ if (old)
97
+ return old;
98
+ }
99
+ return icuLib.ucalClone (val, err);
100
+ }
101
+
73
102
private:
74
103
string asciiName;
75
104
Array<UChar> unicodeName;
105
+ mutable std::atomic<UCalendar*> calendar;
76
106
};
77
107
}
78
108
@@ -593,8 +623,7 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
593
623
594
624
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
595
625
596
- UCalendar* icuCalendar = icuLib.ucalOpen (
597
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
626
+ UCalendar* icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
598
627
599
628
if (!icuCalendar)
600
629
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
@@ -702,8 +731,7 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
702
731
703
732
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
704
733
705
- UCalendar* icuCalendar = icuLib.ucalOpen (
706
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
734
+ UCalendar* icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
707
735
708
736
if (!icuCalendar)
709
737
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
@@ -771,8 +799,7 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
771
799
#endif
772
800
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU ();
773
801
774
- UCalendar* icuCalendar = icuLib.ucalOpen (
775
- getDesc (timeStampTz.time_zone )->getUnicodeName (), -1 , NULL , UCAL_GREGORIAN, &icuErrorCode);
802
+ UCalendar* icuCalendar = getDesc (timeStampTz.time_zone )->getCalendar (icuLib, &icuErrorCode);
776
803
777
804
if (!icuCalendar)
778
805
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
@@ -1067,7 +1094,7 @@ TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& a
1067
1094
{
1068
1095
UErrorCode icuErrorCode = U_ZERO_ERROR;
1069
1096
1070
- icuCalendar = icuLib. ucalOpen ( getDesc (id)->getUnicodeName (), - 1 , NULL , UCAL_GREGORIAN , &icuErrorCode);
1097
+ icuCalendar = getDesc (id)->getCalendar (icuLib , &icuErrorCode);
1071
1098
1072
1099
if (!icuCalendar)
1073
1100
status_exception::raise (Arg::Gds (isc_random) << " Error calling ICU's ucal_open." );
0 commit comments