OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * Copyright (C) 1997-2014, International Business Machines Corporation and * | 3 * Copyright (C) 1997-2015, International Business Machines Corporation and * |
4 * others. All Rights Reserved. * | 4 * others. All Rights Reserved. * |
5 ******************************************************************************* | 5 ******************************************************************************* |
6 * | 6 * |
7 * File CALENDAR.CPP | 7 * File CALENDAR.CPP |
8 * | 8 * |
9 * Modification History: | 9 * Modification History: |
10 * | 10 * |
11 * Date Name Description | 11 * Date Name Description |
12 * 02/03/97 clhuang Creation. | 12 * 02/03/97 clhuang Creation. |
13 * 04/22/97 aliu Cleaned up, fixed memory leak, made | 13 * 04/22/97 aliu Cleaned up, fixed memory leak, made |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 #include "unicode/calendar.h" | 50 #include "unicode/calendar.h" |
51 #include "cpputils.h" | 51 #include "cpputils.h" |
52 #include "servloc.h" | 52 #include "servloc.h" |
53 #include "ucln_in.h" | 53 #include "ucln_in.h" |
54 #include "cstring.h" | 54 #include "cstring.h" |
55 #include "locbased.h" | 55 #include "locbased.h" |
56 #include "uresimp.h" | 56 #include "uresimp.h" |
57 #include "ustrenum.h" | 57 #include "ustrenum.h" |
58 #include "uassert.h" | 58 #include "uassert.h" |
59 #include "olsontz.h" | 59 #include "olsontz.h" |
| 60 #include "sharedcalendar.h" |
| 61 #include "unifiedcache.h" |
60 | 62 |
61 #if !UCONFIG_NO_SERVICE | 63 #if !UCONFIG_NO_SERVICE |
62 static icu::ICULocaleService* gService = NULL; | 64 static icu::ICULocaleService* gService = NULL; |
63 static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; | 65 static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; |
64 #endif | 66 #endif |
65 | 67 |
66 // INTERNAL - for cleanup | 68 // INTERNAL - for cleanup |
67 | 69 |
68 U_CDECL_BEGIN | 70 U_CDECL_BEGIN |
69 static UBool calendar_cleanup(void) { | 71 static UBool calendar_cleanup(void) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 CALTYPE_ETHIOPIC_AMETE_ALEM, | 194 CALTYPE_ETHIOPIC_AMETE_ALEM, |
193 CALTYPE_ISO8601, | 195 CALTYPE_ISO8601, |
194 CALTYPE_DANGI, | 196 CALTYPE_DANGI, |
195 CALTYPE_ISLAMIC_UMALQURA, | 197 CALTYPE_ISLAMIC_UMALQURA, |
196 CALTYPE_ISLAMIC_TBLA, | 198 CALTYPE_ISLAMIC_TBLA, |
197 CALTYPE_ISLAMIC_RGSA | 199 CALTYPE_ISLAMIC_RGSA |
198 } ECalType; | 200 } ECalType; |
199 | 201 |
200 U_NAMESPACE_BEGIN | 202 U_NAMESPACE_BEGIN |
201 | 203 |
| 204 SharedCalendar::~SharedCalendar() { |
| 205 delete ptr; |
| 206 } |
| 207 |
| 208 template<> U_I18N_API |
| 209 const SharedCalendar *LocaleCacheKey<SharedCalendar>::createObject( |
| 210 const void * /*unusedCreationContext*/, UErrorCode &status) const { |
| 211 Calendar *calendar = Calendar::makeInstance(fLoc, status); |
| 212 if (U_FAILURE(status)) { |
| 213 return NULL; |
| 214 } |
| 215 SharedCalendar *shared = new SharedCalendar(calendar); |
| 216 if (shared == NULL) { |
| 217 delete calendar; |
| 218 status = U_MEMORY_ALLOCATION_ERROR; |
| 219 return NULL; |
| 220 } |
| 221 shared->addRef(); |
| 222 return shared; |
| 223 } |
| 224 |
202 static ECalType getCalendarType(const char *s) { | 225 static ECalType getCalendarType(const char *s) { |
203 for (int i = 0; gCalTypes[i] != NULL; i++) { | 226 for (int i = 0; gCalTypes[i] != NULL; i++) { |
204 if (uprv_stricmp(s, gCalTypes[i]) == 0) { | 227 if (uprv_stricmp(s, gCalTypes[i]) == 0) { |
205 return (ECalType)i; | 228 return (ECalType)i; |
206 } | 229 } |
207 } | 230 } |
208 return CALTYPE_UNKNOWN; | 231 return CALTYPE_UNKNOWN; |
209 } | 232 } |
210 | 233 |
211 static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status)
{ | 234 static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status)
{ |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 { 0, 0, 23, 23 }, // HOUR_OF_DAY | 628 { 0, 0, 23, 23 }, // HOUR_OF_DAY |
606 { 0, 0, 59, 59 }, // MINUTE | 629 { 0, 0, 59, 59 }, // MINUTE |
607 { 0, 0, 59, 59 }, // SECOND | 630 { 0, 0, 59, 59 }, // SECOND |
608 { 0, 0, 999, 999 }, // MILLISECOND | 631 { 0, 0, 999, 999 }, // MILLISECOND |
609 {-12*kOneHour, -12*kOneHour, 12*kOneHour, 15*kOneHour }, // ZONE_OFFSET | 632 {-12*kOneHour, -12*kOneHour, 12*kOneHour, 15*kOneHour }, // ZONE_OFFSET |
610 { 0, 0, 1*kOneHour, 1*kOneHour }, // DST_OFFSET | 633 { 0, 0, 1*kOneHour, 1*kOneHour }, // DST_OFFSET |
611 {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // YEAR_WOY | 634 {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // YEAR_WOY |
612 { 1, 1, 7, 7 }, // DOW_LOCAL | 635 { 1, 1, 7, 7 }, // DOW_LOCAL |
613 {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // EXTENDED_YE
AR | 636 {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // EXTENDED_YE
AR |
614 { -0x7F000000, -0x7F000000, 0x7F000000, 0x7F000000 }, // JULIAN_DAY | 637 { -0x7F000000, -0x7F000000, 0x7F000000, 0x7F000000 }, // JULIAN_DAY |
615 { 0, 0, 24*kOneHour-1, 24*kOneHour-1 }, // MILLISECON
DS_IN_DAY | 638 { 0, 0, 24*kOneHour-1, 24*kOneHour-1 }, // MILLISECOND
S_IN_DAY |
616 { 0, 0, 1, 1 }, // IS_LEAP_MO
NTH | 639 { 0, 0, 1, 1 }, // IS_LEAP_MON
TH |
617 }; | 640 }; |
618 | 641 |
619 // Resource bundle tags read by this class | 642 // Resource bundle tags read by this class |
620 static const char gMonthNames[] = "monthNames"; | 643 static const char gMonthNames[] = "monthNames"; |
621 | 644 |
622 // Data flow in Calendar | 645 // Data flow in Calendar |
623 // --------------------- | 646 // --------------------- |
624 | 647 |
625 // The current time is represented in two ways by Calendar: as UTC | 648 // The current time is represented in two ways by Calendar: as UTC |
626 // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local | 649 // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 Calendar* U_EXPORT2 | 849 Calendar* U_EXPORT2 |
827 Calendar::createInstance(const Locale& aLocale, UErrorCode& success) | 850 Calendar::createInstance(const Locale& aLocale, UErrorCode& success) |
828 { | 851 { |
829 return createInstance(TimeZone::createDefault(), aLocale, success); | 852 return createInstance(TimeZone::createDefault(), aLocale, success); |
830 } | 853 } |
831 | 854 |
832 // ------------------------------------- Adopting | 855 // ------------------------------------- Adopting |
833 | 856 |
834 // Note: this is the bottleneck that actually calls the service routines. | 857 // Note: this is the bottleneck that actually calls the service routines. |
835 | 858 |
836 Calendar* U_EXPORT2 | 859 Calendar * U_EXPORT2 |
837 Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
ess) | 860 Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) { |
838 { | |
839 if (U_FAILURE(success)) { | 861 if (U_FAILURE(success)) { |
840 return NULL; | 862 return NULL; |
841 } | 863 } |
842 | 864 |
843 Locale actualLoc; | 865 Locale actualLoc; |
844 UObject* u = NULL; | 866 UObject* u = NULL; |
845 | 867 |
846 #if !UCONFIG_NO_SERVICE | 868 #if !UCONFIG_NO_SERVICE |
847 if (isCalendarServiceUsed()) { | 869 if (isCalendarServiceUsed()) { |
848 u = getCalendarService(success)->get(aLocale, LocaleKey::KIND_ANY, &actu
alLoc, success); | 870 u = getCalendarService(success)->get(aLocale, LocaleKey::KIND_ANY, &actu
alLoc, success); |
849 } | 871 } |
850 else | 872 else |
851 #endif | 873 #endif |
852 { | 874 { |
853 u = createStandardCalendar(getCalendarTypeForLocale(aLocale.getName()),
aLocale, success); | 875 u = createStandardCalendar(getCalendarTypeForLocale(aLocale.getName()),
aLocale, success); |
854 } | 876 } |
855 Calendar* c = NULL; | 877 Calendar* c = NULL; |
856 | 878 |
857 if(U_FAILURE(success) || !u) { | 879 if(U_FAILURE(success) || !u) { |
858 delete zone; | |
859 if(U_SUCCESS(success)) { // Propagate some kind of err | 880 if(U_SUCCESS(success)) { // Propagate some kind of err |
860 success = U_INTERNAL_PROGRAM_ERROR; | 881 success = U_INTERNAL_PROGRAM_ERROR; |
861 } | 882 } |
862 return NULL; | 883 return NULL; |
863 } | 884 } |
864 | 885 |
865 #if !UCONFIG_NO_SERVICE | 886 #if !UCONFIG_NO_SERVICE |
866 const UnicodeString* str = dynamic_cast<const UnicodeString*>(u); | 887 const UnicodeString* str = dynamic_cast<const UnicodeString*>(u); |
867 if(str != NULL) { | 888 if(str != NULL) { |
868 // It's a unicode string telling us what type of calendar to load ("greg
orian", etc) | 889 // It's a unicode string telling us what type of calendar to load ("greg
orian", etc) |
869 // Create a Locale over this string | 890 // Create a Locale over this string |
870 Locale l(""); | 891 Locale l(""); |
871 LocaleUtility::initLocaleFromName(*str, l); | 892 LocaleUtility::initLocaleFromName(*str, l); |
872 | 893 |
873 #ifdef U_DEBUG_CALSVC | 894 #ifdef U_DEBUG_CALSVC |
874 fprintf(stderr, "Calendar::createInstance(%s), looking up [%s]\n", aLoca
le.getName(), l.getName()); | 895 fprintf(stderr, "Calendar::createInstance(%s), looking up [%s]\n", aLoca
le.getName(), l.getName()); |
875 #endif | 896 #endif |
876 | 897 |
877 Locale actualLoc2; | 898 Locale actualLoc2; |
878 delete u; | 899 delete u; |
879 u = NULL; | 900 u = NULL; |
880 | 901 |
881 // Don't overwrite actualLoc, since the actual loc from this call | 902 // Don't overwrite actualLoc, since the actual loc from this call |
882 // may be something like "@calendar=gregorian" -- TODO investigate | 903 // may be something like "@calendar=gregorian" -- TODO investigate |
883 // further... | 904 // further... |
884 c = (Calendar*)getCalendarService(success)->get(l, LocaleKey::KIND_ANY,
&actualLoc2, success); | 905 c = (Calendar*)getCalendarService(success)->get(l, LocaleKey::KIND_ANY,
&actualLoc2, success); |
885 | 906 |
886 if(U_FAILURE(success) || !c) { | 907 if(U_FAILURE(success) || !c) { |
887 delete zone; | |
888 if(U_SUCCESS(success)) { | 908 if(U_SUCCESS(success)) { |
889 success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err | 909 success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err |
890 } | 910 } |
891 return NULL; | 911 return NULL; |
892 } | 912 } |
893 | 913 |
894 str = dynamic_cast<const UnicodeString*>(c); | 914 str = dynamic_cast<const UnicodeString*>(c); |
895 if(str != NULL) { | 915 if(str != NULL) { |
896 // recursed! Second lookup returned a UnicodeString. | 916 // recursed! Second lookup returned a UnicodeString. |
897 // Perhaps DefaultCalendar{} was set to another locale. | 917 // Perhaps DefaultCalendar{} was set to another locale. |
898 #ifdef U_DEBUG_CALSVC | 918 #ifdef U_DEBUG_CALSVC |
899 char tmp[200]; | 919 char tmp[200]; |
900 // Extract a char* out of it.. | 920 // Extract a char* out of it.. |
901 int32_t len = str->length(); | 921 int32_t len = str->length(); |
902 int32_t actLen = sizeof(tmp)-1; | 922 int32_t actLen = sizeof(tmp)-1; |
903 if(len > actLen) { | 923 if(len > actLen) { |
904 len = actLen; | 924 len = actLen; |
905 } | 925 } |
906 str->extract(0,len,tmp); | 926 str->extract(0,len,tmp); |
907 tmp[len]=0; | 927 tmp[len]=0; |
908 | 928 |
909 fprintf(stderr, "err - recursed, 2nd lookup was unistring %s\n", tmp
); | 929 fprintf(stderr, "err - recursed, 2nd lookup was unistring %s\n", tmp
); |
910 #endif | 930 #endif |
911 success = U_MISSING_RESOURCE_ERROR; // requested a calendar type wh
ich could NOT be found. | 931 success = U_MISSING_RESOURCE_ERROR; // requested a calendar type wh
ich could NOT be found. |
912 delete c; | 932 delete c; |
913 delete zone; | |
914 return NULL; | 933 return NULL; |
915 } | 934 } |
916 #ifdef U_DEBUG_CALSVC | 935 #ifdef U_DEBUG_CALSVC |
917 fprintf(stderr, "%p: setting week count data to locale %s, actual locale
%s\n", c, (const char*)aLocale.getName(), (const char *)actualLoc.getName()); | 936 fprintf(stderr, "%p: setting week count data to locale %s, actual locale
%s\n", c, (const char*)aLocale.getName(), (const char *)actualLoc.getName()); |
918 #endif | 937 #endif |
919 c->setWeekData(aLocale, c->getType(), success); // set the correct loca
le (this was an indirected calendar) | 938 c->setWeekData(aLocale, c->getType(), success); // set the correct loca
le (this was an indirected calendar) |
920 | 939 |
921 char keyword[ULOC_FULLNAME_CAPACITY]; | 940 char keyword[ULOC_FULLNAME_CAPACITY]; |
922 UErrorCode tmpStatus = U_ZERO_ERROR; | 941 UErrorCode tmpStatus = U_ZERO_ERROR; |
923 l.getKeywordValue("calendar", keyword, ULOC_FULLNAME_CAPACITY, tmpStatus
); | 942 l.getKeywordValue("calendar", keyword, ULOC_FULLNAME_CAPACITY, tmpStatus
); |
924 if (U_SUCCESS(tmpStatus) && uprv_strcmp(keyword, "iso8601") == 0) { | 943 if (U_SUCCESS(tmpStatus) && uprv_strcmp(keyword, "iso8601") == 0) { |
925 c->setFirstDayOfWeek(UCAL_MONDAY); | 944 c->setFirstDayOfWeek(UCAL_MONDAY); |
926 c->setMinimalDaysInFirstWeek(4); | 945 c->setMinimalDaysInFirstWeek(4); |
927 } | 946 } |
928 } | 947 } |
929 else | 948 else |
930 #endif /* UCONFIG_NO_SERVICE */ | 949 #endif /* UCONFIG_NO_SERVICE */ |
931 { | 950 { |
932 // a calendar was returned - we assume the factory did the right thing. | 951 // a calendar was returned - we assume the factory did the right thing. |
933 c = (Calendar*)u; | 952 c = (Calendar*)u; |
934 } | 953 } |
935 | 954 |
| 955 return c; |
| 956 } |
| 957 |
| 958 Calendar* U_EXPORT2 |
| 959 Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
ess) |
| 960 { |
| 961 LocalPointer<TimeZone> zonePtr(zone); |
| 962 const SharedCalendar *shared = NULL; |
| 963 UnifiedCache::getByLocale(aLocale, shared, success); |
| 964 if (U_FAILURE(success)) { |
| 965 return NULL; |
| 966 } |
| 967 Calendar *c = (*shared)->clone(); |
| 968 shared->removeRef(); |
| 969 if (c == NULL) { |
| 970 success = U_MEMORY_ALLOCATION_ERROR; |
| 971 return NULL; |
| 972 } |
| 973 |
936 // Now, reset calendar to default state: | 974 // Now, reset calendar to default state: |
937 c->adoptTimeZone(zone); // Set the correct time zone | 975 c->adoptTimeZone(zonePtr.orphan()); // Set the correct time zone |
938 c->setTimeInMillis(getNow(), success); // let the new calendar have the curr
ent time. | 976 c->setTimeInMillis(getNow(), success); // let the new calendar have the curr
ent time. |
939 | 977 |
940 return c; | 978 return c; |
941 } | 979 } |
942 | 980 |
943 // ------------------------------------- | 981 // ------------------------------------- |
944 | 982 |
945 Calendar* U_EXPORT2 | 983 Calendar* U_EXPORT2 |
946 Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode
& success) | 984 Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode
& success) |
947 { | 985 { |
948 Calendar* c = createInstance(aLocale, success); | 986 Calendar* c = createInstance(aLocale, success); |
949 if(U_SUCCESS(success) && c) { | 987 if(U_SUCCESS(success) && c) { |
950 c->setTimeZone(zone); | 988 c->setTimeZone(zone); |
951 } | 989 } |
952 return c; | 990 return c; |
953 } | 991 } |
954 | 992 |
955 // ------------------------------------- | 993 // ------------------------------------- |
956 | 994 |
| 995 void U_EXPORT2 |
| 996 Calendar::getCalendarTypeFromLocale( |
| 997 const Locale &aLocale, |
| 998 char *typeBuffer, |
| 999 int32_t typeBufferSize, |
| 1000 UErrorCode &success) { |
| 1001 const SharedCalendar *shared = NULL; |
| 1002 UnifiedCache::getByLocale(aLocale, shared, success); |
| 1003 if (U_FAILURE(success)) { |
| 1004 return; |
| 1005 } |
| 1006 uprv_strncpy(typeBuffer, (*shared)->getType(), typeBufferSize); |
| 1007 shared->removeRef(); |
| 1008 if (typeBuffer[typeBufferSize - 1]) { |
| 1009 success = U_BUFFER_OVERFLOW_ERROR; |
| 1010 } |
| 1011 } |
| 1012 |
957 UBool | 1013 UBool |
958 Calendar::operator==(const Calendar& that) const | 1014 Calendar::operator==(const Calendar& that) const |
959 { | 1015 { |
960 UErrorCode status = U_ZERO_ERROR; | 1016 UErrorCode status = U_ZERO_ERROR; |
961 return isEquivalentTo(that) && | 1017 return isEquivalentTo(that) && |
962 getTimeInMillis(status) == that.getTimeInMillis(status) && | 1018 getTimeInMillis(status) == that.getTimeInMillis(status) && |
963 U_SUCCESS(status); | 1019 U_SUCCESS(status); |
964 } | 1020 } |
965 | 1021 |
966 UBool | 1022 UBool |
(...skipping 2899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3866 return NULL; | 3922 return NULL; |
3867 } | 3923 } |
3868 | 3924 |
3869 U_NAMESPACE_END | 3925 U_NAMESPACE_END |
3870 | 3926 |
3871 #endif /* #if !UCONFIG_NO_FORMATTING */ | 3927 #endif /* #if !UCONFIG_NO_FORMATTING */ |
3872 | 3928 |
3873 | 3929 |
3874 //eof | 3930 //eof |
3875 | 3931 |
OLD | NEW |