From: Apple Date: Tue, 11 Mar 2014 22:52:33 +0000 (+0000) Subject: ICU-511.32.tar.gz X-Git-Tag: os-x-1093^0 X-Git-Url: https://git.saurik.com/apple/icu.git/commitdiff_plain/e4f10fab0c078f399c9deef476d9c9b73b47dff8 ICU-511.32.tar.gz --- diff --git a/icuSources/data/misc/metaZones.txt b/icuSources/data/misc/metaZones.txt index da466334..ac8dbd2b 100644 --- a/icuSources/data/misc/metaZones.txt +++ b/icuSources/data/misc/metaZones.txt @@ -2062,11 +2062,6 @@ metaZones:table(nofallback){ "Uruguay", } } - "America:Montreal"{ - { - "America_Eastern", - } - } "America:Montserrat"{ { "Atlantic", @@ -2358,11 +2353,6 @@ metaZones:table(nofallback){ "9999-12-31 23:59", } } - "America:Shiprock"{ - { - "America_Mountain", - } - } "America:Sitka"{ { "America_Pacific", @@ -3576,11 +3566,11 @@ metaZones:table(nofallback){ { "Moscow", "1970-01-01 00:00", - "1990-06-30 23:00", + "1990-06-30 22:00", } { "Europe_Eastern", - "1990-06-30 23:00", + "1990-06-30 22:00", "9999-12-31 23:59", } } diff --git a/icuSources/data/misc/zoneinfo64.txt b/icuSources/data/misc/zoneinfo64.txt index 0f8dc6c3..85271c2d 100644 --- a/icuSources/data/misc/zoneinfo64.txt +++ b/icuSources/data/misc/zoneinfo64.txt @@ -3,17 +3,17 @@ // Corporation and others. All Rights Reserved. //--------------------------------------------------------- // Build tool: tz2icu -// Build date: Fri Jan 3 16:38:37 2014 +// Build date: Mon Mar 10 15:09:10 2014 // Olson source: ftp://elsie.nci.nih.gov/pub/ -// Olson version: 2013i -// ICU version: 53.0.1 +// Olson version: 2014a +// ICU version: 53.1 //--------------------------------------------------------- // >> !!! >> THIS IS A MACHINE-GENERATED FILE << !!! << // >> !!! >>> DO NOT EDIT <<< !!! << //--------------------------------------------------------- zoneinfo64:table(nofallback) { - TZVersion { "2013i" } + TZVersion { "2014a" } Zones:array { /* ACT */ :int { 344 } //Z#0 /* AET */ :int { 356 } //Z#1 @@ -1514,7 +1514,7 @@ zoneinfo64:table(nofallback) { } //Z#260 /* Asia/Gaza */ :table { transPre32:intvector { -1, 2109557424 } - trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576540000, 589237200, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1219957200, 1238104800, 1252015200, 1269640860, 1281474000, 1301608860, 1312146000, 1333058400, 1348178400, 1364508000, 1380229200 } + trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1219957200, 1238104800, 1252015200, 1269640860, 1281474000, 1301608860, 1312146000, 1333058400, 1348178400, 1364508000, 1380229200 } typeOffsets:intvector { 8272, 0, 7200, 0, 7200, 3600 } typeMap:bin { "0102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" } finalRule { "Palestine" } @@ -1528,7 +1528,7 @@ zoneinfo64:table(nofallback) { } //Z#262 /* Asia/Hebron */ :table { transPre32:intvector { -1, 2109557273 } - trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576540000, 589237200, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1220216400, 1238104800, 1252015200, 1269554400, 1281474000, 1301608860, 1312146000, 1314655200, 1317330000, 1333058400, 1348178400, 1364508000, 1380229200 } + trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1220216400, 1238104800, 1252015200, 1269554400, 1281474000, 1301608860, 1312146000, 1314655200, 1317330000, 1333058400, 1348178400, 1364508000, 1380229200 } typeOffsets:intvector { 8423, 0, 7200, 0, 7200, 3600 } typeMap:bin { "01020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" } finalRule { "Palestine" } @@ -1570,7 +1570,7 @@ zoneinfo64:table(nofallback) { } //Z#270 /* Asia/Jerusalem */ :table { transPre32:intvector { -1, 1454818042 } - trans:intvector { -1641003640, -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -681962400, -673243200, -667962000, -652327200, -636426000, -622087200, -608947200, -591847200, -572486400, -558576000, -542851200, -527731200, -514425600, -490845600, -482986800, -459475200, -451537200, -428551200, -418262400, -400032000, -387428400, 142380000, 150843600, 167176800, 178664400, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576540000, 589237200, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 826840800, 842821200, 858895200, 874184400, 890344800, 905029200, 923011200, 936313200, 955670400, 970783200, 986770800, 1001282400, 1017356400, 1033941600, 1048806000, 1065132000, 1081292400, 1095804000, 1112313600, 1128812400, 1143763200, 1159657200, 1175212800, 1189897200, 1206662400, 1223161200, 1238112000, 1254006000, 1269561600, 1284246000, 1301616000, 1317510000, 1333065600, 1348354800, 1364515200, 1382828400 } + trans:intvector { -1641003640, -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -681962400, -673243200, -667962000, -652327200, -636426000, -622087200, -608947200, -591847200, -572486400, -558576000, -542851200, -527731200, -514425600, -490845600, -482986800, -459475200, -451537200, -428551200, -418262400, -400032000, -387428400, 142380000, 150843600, 167176800, 178664400, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 826840800, 842821200, 858895200, 874184400, 890344800, 905029200, 923011200, 936313200, 955670400, 970783200, 986770800, 1001282400, 1017356400, 1033941600, 1048806000, 1065132000, 1081292400, 1095804000, 1112313600, 1128812400, 1143763200, 1159657200, 1175212800, 1189897200, 1206662400, 1223161200, 1238112000, 1254006000, 1269561600, 1284246000, 1301616000, 1317510000, 1333065600, 1348354800, 1364515200, 1382828400 } typeOffsets:intvector { 8454, 0, 7200, 0, 7200, 3600, 7200, 7200, 8440, 0 } typeMap:bin { "0401020102010201020102010302010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" } finalRule { "Zion" } @@ -2314,12 +2314,12 @@ zoneinfo64:table(nofallback) { /* Europe/Isle_of_Man */ :int { 452 } //Z#445 /* Europe/Istanbul */ :table { transPre32:intvector { -1, 1454819544 } - trans:intvector { -1869875816, -1693706400, -1680490800, -1570413600, -1552186800, -1538359200, -1522551600, -1507514400, -1490583600, -1440208800, -1428030000, -1409709600, -1396494000, -931140000, -922762800, -917834400, -892436400, -875844000, -857358000, -781063200, -764737200, -744343200, -733806000, -716436000, -701924400, -684986400, -670474800, -654141600, -639025200, -621828000, -606970800, -590032800, -575434800, -235620000, -228279600, -177732000, -165726000, 10533600, 23835600, 41983200, 55285200, 74037600, 87339600, 107910000, 121219200, 133920000, 152676000, 165362400, 183502800, 202428000, 215557200, 228866400, 245797200, 260316000, 277246800, 308779200, 323827200, 340228800, 354672000, 371678400, 386121600, 403128000, 428446800, 433886400, 482792400, 496702800, 512524800, 528249600, 543974400, 559699200, 575424000, 591148800, 606873600, 622598400, 638323200, 654652800, 670374000, 686098800, 701823600, 717548400, 733273200, 748998000, 764722800, 780447600, 796172400, 811897200, 828226800, 846370800, 859676400, 877820400, 891126000, 909270000, 922575600, 941324400, 954025200, 972774000, 985474800, 1004223600, 1017529200, 1035673200, 1048978800, 1067122800, 1080428400, 1099177200, 1111878000, 1130626800, 1143327600, 1162076400, 1174784400, 1193533200, 1206838800, 1224982800, 1238288400, 1256432400, 1269738000, 1288486800, 1301274000, 1319936400, 1332637200, 1351386000 } + trans:intvector { -1869875816, -1693706400, -1680490800, -1570413600, -1552186800, -1538359200, -1522551600, -1507514400, -1490583600, -1440208800, -1428030000, -1409709600, -1396494000, -931140000, -922762800, -917834400, -892436400, -875844000, -857358000, -781063200, -764737200, -744343200, -733806000, -716436000, -701924400, -684986400, -670474800, -654141600, -639025200, -621828000, -606970800, -590032800, -575434800, -235620000, -228279600, -177732000, -165726000, 10533600, 23835600, 41983200, 55285200, 74037600, 87339600, 107910000, 121219200, 133920000, 152676000, 165362400, 183502800, 202428000, 215557200, 228866400, 245797200, 260316000, 277246800, 308779200, 323827200, 340228800, 354672000, 371678400, 386121600, 403128000, 428446800, 433886400, 482792400, 496702800, 512524800, 528249600, 543974400, 559699200, 575424000, 591148800, 606873600, 622598400, 638323200, 654652800, 670374000, 686098800, 701823600, 717548400, 733273200, 748998000, 764722800, 780447600, 796172400, 811897200, 828226800, 846370800, 859676400, 877820400, 891126000, 909270000, 922575600, 941324400, 954025200, 972774000, 985474800, 1004223600, 1017529200, 1035673200, 1048978800, 1067122800, 1080428400, 1099177200, 1111878000, 1130626800, 1143327600, 1162076400, 1174784400, 1193533200, 1206838800, 1224982800, 1238288400, 1256432400, 1269738000, 1288486800, 1301274000, 1319936400, 1332637200, 1351386000, 1364691600, 1382835600, 1396227600, 1414285200, 1427590800, 1445734800 } typeOffsets:intvector { 6952, 0, 7016, 0, 7200, 0, 7200, 3600, 10800, 0, 10800, 3600 } - typeMap:bin { "01020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203050405040504050405040302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302" } + typeMap:bin { "01020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203050405040504050405040302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302" } finalRule { "EU" } finalRaw:int { 7200 } - finalYear:int { 2013 } + finalYear:int { 2016 } links:intvector { 268, 446, 597 } } //Z#446 /* Europe/Jersey */ :int { 452 } //Z#447 @@ -2330,9 +2330,9 @@ zoneinfo64:table(nofallback) { typeMap:bin { "010201020102010201020102010304030506050605060506050605060506050605060506050403040304030403040304030403040304030403040304030403040304030403040304030403040305" } } //Z#448 /* Europe/Kiev */ :table { - trans:intvector { -1441159324, -1247536800, -892522800, -857257200, -844556400, -828226800, -825382800, 354920400, 370728000, 386456400, 402264000, 417992400, 433800000, 449614800, 465346800, 481071600, 496796400, 512521200, 528246000, 543970800, 559695600, 575420400, 591145200, 606870000, 622594800, 646786800, 701820000, 717541200, 733269600, 748990800, 764719200, 780440400, 796179600, 811904400, 828234000, 846378000 } + trans:intvector { -1441159324, -1247536800, -892522800, -857257200, -844556400, -828226800, -825382800, 354920400, 370728000, 386456400, 402264000, 417992400, 433800000, 449614800, 465346800, 481071600, 496796400, 512521200, 528246000, 543970800, 559695600, 575420400, 591145200, 606870000, 622594800, 638319600, 646783200, 686102400, 701820000, 717541200, 733269600, 748990800, 764719200, 780440400, 796179600, 811904400, 828234000, 846378000 } typeOffsets:intvector { 7324, 0, 3600, 0, 3600, 3600, 7200, 0, 7200, 3600, 10800, 0, 10800, 3600 } - typeMap:bin { "030502010201050605060506050605060506050605060506050304030403040304030403" } + typeMap:bin { "0305020102010506050605060506050605060506050605060506040304030403040304030403" } finalRule { "EU" } finalRaw:int { 7200 } finalYear:int { 1997 } @@ -2753,12 +2753,12 @@ zoneinfo64:table(nofallback) { typeMap:bin { "0102" } } //Z#543 /* Pacific/Fiji */ :table { - trans:intvector { -1709985344, 909842400, 920124000, 941896800, 951573600, 1259416800, 1269698400, 1287842400, 1299333600, 1319292000, 1327154400, 1350741600 } + trans:intvector { -1709985344, 909842400, 920124000, 941896800, 951573600, 1259416800, 1269698400, 1287842400, 1299333600, 1319292000, 1327154400, 1350741600, 1358604000, 1382796000, 1390050000, 1414245600 } typeOffsets:intvector { 42944, 0, 43200, 0, 43200, 3600 } - typeMap:bin { "010201020102010201020102" } + typeMap:bin { "01020102010201020102010201020102" } finalRule { "Fiji" } finalRaw:int { 43200 } - finalYear:int { 2013 } + finalYear:int { 2015 } } //Z#544 /* Pacific/Funafuti */ :table { transPre32:intvector { -1, 2117471484 } @@ -3259,7 +3259,7 @@ zoneinfo64:table(nofallback) { 2, -31, -1, 3600, 2, 9, -31, -1, 3600, 2, 3600 } //_#13 Fiji:intvector { - 9, 21, -1, 7200, 0, 0, 18, -1, 10800, 0, 3600 + 9, 21, -1, 7200, 0, 0, 18, -1, 7200, 0, 3600 } //_#14 Haiti:intvector { 2, 8, -1, 7200, 0, 10, 1, -1, 7200, 0, 3600 @@ -3486,7 +3486,7 @@ zoneinfo64:table(nofallback) { "CA", //Z#166 America/Moncton "MX", //Z#167 America/Monterrey "UY", //Z#168 America/Montevideo - "CA", //Z#169 America/Montreal + "001",//Z#169 America/Montreal "MS", //Z#170 America/Montserrat "BS", //Z#171 America/Nassau "US", //Z#172 America/New_York diff --git a/icuSources/i18n/calendar.cpp b/icuSources/i18n/calendar.cpp index 4edd2610..88730a2c 100644 --- a/icuSources/i18n/calendar.cpp +++ b/icuSources/i18n/calendar.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 1997-2013, International Business Machines Corporation and * +* Copyright (C) 1997-2014, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* * @@ -1892,10 +1892,10 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status // a computed amount of millis to the current millis. The only // wrinkle is with DST (and/or a change to the zone's UTC offset, which // we'll include with DST) -- for some fields, like the DAY_OF_MONTH, - // we don't want the HOUR to shift due to changes in DST. If the + // we don't want the wall time to shift due to changes in DST. If the // result of the add operation is to move from DST to Standard, or // vice versa, we need to adjust by an hour forward or back, - // respectively. For such fields we set keepHourInvariant to TRUE. + // respectively. For such fields we set keepWallTimeInvariant to TRUE. // We only adjust the DST for fields larger than an hour. For // fields smaller than an hour, we cannot adjust for DST without @@ -1910,7 +1910,7 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status // , rather than => . double delta = amount; // delta in ms - UBool keepHourInvariant = TRUE; + UBool keepWallTimeInvariant = TRUE; switch (field) { case UCAL_ERA: @@ -1972,22 +1972,22 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status case UCAL_HOUR_OF_DAY: case UCAL_HOUR: delta *= kOneHour; - keepHourInvariant = FALSE; + keepWallTimeInvariant = FALSE; break; case UCAL_MINUTE: delta *= kOneMinute; - keepHourInvariant = FALSE; + keepWallTimeInvariant = FALSE; break; case UCAL_SECOND: delta *= kOneSecond; - keepHourInvariant = FALSE; + keepWallTimeInvariant = FALSE; break; case UCAL_MILLISECOND: case UCAL_MILLISECONDS_IN_DAY: - keepHourInvariant = FALSE; + keepWallTimeInvariant = FALSE; break; default: @@ -2001,41 +2001,61 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status // ") not supported"); } - // In order to keep the hour invariant (for fields where this is + // In order to keep the wall time invariant (for fields where this is // appropriate), check the combined DST & ZONE offset before and // after the add() operation. If it changes, then adjust the millis // to compensate. int32_t prevOffset = 0; - int32_t hour = 0; - if (keepHourInvariant) { + int32_t prevWallTime = 0; + if (keepWallTimeInvariant) { prevOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status); - hour = internalGet(UCAL_HOUR_OF_DAY); + prevWallTime = get(UCAL_MILLISECONDS_IN_DAY, status); } setTimeInMillis(getTimeInMillis(status) + delta, status); - if (keepHourInvariant) { - int32_t newOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status); - if (newOffset != prevOffset) { - // We have done an hour-invariant adjustment but the - // combined offset has changed. We adjust millis to keep - // the hour constant. In cases such as midnight after - // a DST change which occurs at midnight, there is the - // danger of adjusting into a different day. To avoid - // this we make the adjustment only if it actually - // maintains the hour. - - // When the difference of the previous UTC offset and - // the new UTC offset exceeds 1 full day, we do not want - // to roll over/back the date. For now, this only happens - // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452. - int32_t adjAmount = prevOffset - newOffset; - adjAmount = adjAmount >= 0 ? adjAmount % (int32_t)kOneDay : -(-adjAmount % (int32_t)kOneDay); - if (adjAmount != 0) { - double t = internalGetTime(); - setTimeInMillis(t + adjAmount, status); - if (get(UCAL_HOUR_OF_DAY, status) != hour) { - setTimeInMillis(t, status); + if (keepWallTimeInvariant) { + int32_t newWallTime = get(UCAL_MILLISECONDS_IN_DAY, status); + if (newWallTime != prevWallTime) { + // There is at least one zone transition between the base + // time and the result time. As the result, wall time has + // changed. + UDate t = internalGetTime(); + int32_t newOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status); + if (newOffset != prevOffset) { + // When the difference of the previous UTC offset and + // the new UTC offset exceeds 1 full day, we do not want + // to roll over/back the date. For now, this only happens + // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452. + int32_t adjAmount = prevOffset - newOffset; + adjAmount = adjAmount >= 0 ? adjAmount % (int32_t)kOneDay : -(-adjAmount % (int32_t)kOneDay); + if (adjAmount != 0) { + setTimeInMillis(t + adjAmount, status); + newWallTime = get(UCAL_MILLISECONDS_IN_DAY, status); + } + if (newWallTime != prevWallTime) { + // The result wall time or adjusted wall time was shifted because + // the target wall time does not exist on the result date. + switch (fSkippedWallTime) { + case UCAL_WALLTIME_FIRST: + if (adjAmount > 0) { + setTimeInMillis(t, status); + } + break; + case UCAL_WALLTIME_LAST: + if (adjAmount < 0) { + setTimeInMillis(t, status); + } + break; + case UCAL_WALLTIME_NEXT_VALID: + UDate tmpT = adjAmount > 0 ? internalGetTime() : t; + UDate immediatePrevTrans; + UBool hasTransition = getImmediatePreviousZoneTransition(tmpT, &immediatePrevTrans, status); + if (U_SUCCESS(status) && hasTransition) { + setTimeInMillis(immediatePrevTrans, status); + } + break; + } } } } @@ -2847,22 +2867,10 @@ void Calendar::computeTime(UErrorCode& status) { // Adjust time to the next valid wall clock time. // At this point, tmpTime is on or after the zone offset transition causing // the skipped time range. - - BasicTimeZone *btz = getBasicTimeZone(); - if (btz) { - TimeZoneTransition transition; - UBool hasTransition = btz->getPreviousTransition(tmpTime, TRUE, transition); - if (hasTransition) { - t = transition.getTime(); - } else { - // Could not find any transitions. - // Note: This should never happen. - status = U_INTERNAL_PROGRAM_ERROR; - } - } else { - // If not BasicTimeZone, return unsupported error for now. - // TODO: We may support non-BasicTimeZone in future. - status = U_UNSUPPORTED_ERROR; + UDate immediatePrevTransition; + UBool hasTransition = getImmediatePreviousZoneTransition(tmpTime, &immediatePrevTransition, status); + if (U_SUCCESS(status) && hasTransition) { + t = immediatePrevTransition; } } } else { @@ -2878,6 +2886,30 @@ void Calendar::computeTime(UErrorCode& status) { } } +/** + * Find the previous zone transtion near the given time. + */ +UBool Calendar::getImmediatePreviousZoneTransition(UDate base, UDate *transitionTime, UErrorCode& status) const { + BasicTimeZone *btz = getBasicTimeZone(); + if (btz) { + TimeZoneTransition trans; + UBool hasTransition = btz->getPreviousTransition(base, TRUE, trans); + if (hasTransition) { + *transitionTime = trans.getTime(); + return TRUE; + } else { + // Could not find any transitions. + // Note: This should never happen. + status = U_INTERNAL_PROGRAM_ERROR; + } + } else { + // If not BasicTimeZone, return unsupported error for now. + // TODO: We may support non-BasicTimeZone in future. + status = U_UNSUPPORTED_ERROR; + } + return FALSE; +} + /** * Compute the milliseconds in the day from the fields. This is a * value from 0 to 23:59:59.999 inclusive, unless fields are out of diff --git a/icuSources/i18n/unicode/calendar.h b/icuSources/i18n/unicode/calendar.h index 6832939a..24b0cbef 100644 --- a/icuSources/i18n/unicode/calendar.h +++ b/icuSources/i18n/unicode/calendar.h @@ -1,6 +1,6 @@ /* ******************************************************************************** -* Copyright (C) 1997-2013, International Business Machines +* Copyright (C) 1997-2014, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************** * @@ -2428,6 +2428,15 @@ private: * is not an instance of BasicTimeZone. */ BasicTimeZone* getBasicTimeZone() const; + + /** + * Find the previous zone transtion near the given time. + * @param base The base time, inclusive + * @param transitionTime Receives the result time + * @param status The error status + * @return TRUE if a transition is found. + */ + UBool getImmediatePreviousZoneTransition(UDate base, UDate *transitionTime, UErrorCode& status) const; }; // ------------------------------------- diff --git a/icuSources/test/intltest/caltest.cpp b/icuSources/test/intltest/caltest.cpp index 5795160c..01f1407a 100644 --- a/icuSources/test/intltest/caltest.cpp +++ b/icuSources/test/intltest/caltest.cpp @@ -1,6 +1,6 @@ /************************************************************************ * COPYRIGHT: - * Copyright (c) 1997-2012, International Business Machines Corporation + * Copyright (c) 1997-2014, International Business Machines Corporation * and others. All Rights Reserved. ************************************************************************/ @@ -279,6 +279,13 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, TestCloneLocale(); } break; + case 31: + name = "TestAddAcrossZoneTransition"; + if(exec) { + logln("TestAddAcrossZoneTransition---"); logln(""); + TestAddAcrossZoneTransition(); + } + break; default: name = ""; break; } } @@ -2389,12 +2396,13 @@ CalendarTest::TestAmbiguousWallTimeAPIs(void) { class CalFields { public: - CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec); + CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t ms = 0); CalFields(const Calendar& cal, UErrorCode& status); void setTo(Calendar& cal) const; char* toString(char* buf, int32_t len) const; UBool operator==(const CalFields& rhs) const; UBool operator!=(const CalFields& rhs) const; + UBool isEquivalentTo(const Calendar& cal, UErrorCode& status) const; private: int32_t year; @@ -2403,10 +2411,11 @@ private: int32_t hour; int32_t min; int32_t sec; + int32_t ms; }; -CalFields::CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec) - : year(year), month(month), day(day), hour(hour), min(min), sec(sec) { +CalFields::CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t ms) + : year(year), month(month), day(day), hour(hour), min(min), sec(sec), ms(ms) { } CalFields::CalFields(const Calendar& cal, UErrorCode& status) { @@ -2416,18 +2425,20 @@ CalFields::CalFields(const Calendar& cal, UErrorCode& status) { hour = cal.get(UCAL_HOUR_OF_DAY, status); min = cal.get(UCAL_MINUTE, status); sec = cal.get(UCAL_SECOND, status); + ms = cal.get(UCAL_MILLISECOND, status); } void CalFields::setTo(Calendar& cal) const { cal.clear(); cal.set(year, month - 1, day, hour, min, sec); + cal.set(UCAL_MILLISECOND, ms); } char* CalFields::toString(char* buf, int32_t len) const { char local[32]; - sprintf(local, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec); + sprintf(local, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, min, sec, ms); uprv_strncpy(buf, local, len - 1); buf[len - 1] = 0; return buf; @@ -2440,7 +2451,8 @@ CalFields::operator==(const CalFields& rhs) const { && day == rhs.day && hour == rhs.hour && min == rhs.min - && sec == rhs.sec; + && sec == rhs.sec + && ms == rhs.ms; } UBool @@ -2448,6 +2460,17 @@ CalFields::operator!=(const CalFields& rhs) const { return !(*this == rhs); } +UBool +CalFields::isEquivalentTo(const Calendar& cal, UErrorCode& status) const { + return year == cal.get(UCAL_YEAR, status) + && month == cal.get(UCAL_MONTH, status) + 1 + && day == cal.get(UCAL_DAY_OF_MONTH, status) + && hour == cal.get(UCAL_HOUR_OF_DAY, status) + && min == cal.get(UCAL_MINUTE, status) + && sec == cal.get(UCAL_SECOND, status) + && ms == cal.get(UCAL_MILLISECOND, status); +} + typedef struct { const char* tzid; const CalFields in; @@ -2716,6 +2739,183 @@ void CalendarTest::TestCloneLocale(void) { TEST_CHECK_STATUS; } +typedef struct { + const char* zone; + const CalFields base; + int32_t deltaDays; + UCalendarWallTimeOption skippedWTOpt; + const CalFields expected; +} TestAddAcrossZoneTransitionData; + +static const TestAddAcrossZoneTransitionData AAZTDATA[] = +{ + // Time zone Base wall time day(s) Skipped time options + // Expected wall time + + // Add 1 day, from the date before DST transition + {"America/Los_Angeles", CalFields(2014,3,8,1,59,59,999), 1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,1,59,59,999)}, + + {"America/Los_Angeles", CalFields(2014,3,8,1,59,59,999), 1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,1,59,59,999)}, + + {"America/Los_Angeles", CalFields(2014,3,8,1,59,59,999), 1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,1,59,59,999)}, + + + {"America/Los_Angeles", CalFields(2014,3,8,2,0,0,0), 1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,1,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,8,2,0,0,0), 1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,3,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,8,2,0,0,0), 1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,3,0,0,0)}, + + + {"America/Los_Angeles", CalFields(2014,3,8,2,30,0,0), 1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,1,30,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,8,2,30,0,0), 1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,3,30,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,8,2,30,0,0), 1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,3,0,0,0)}, + + + {"America/Los_Angeles", CalFields(2014,3,8,3,0,0,0), 1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,3,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,8,3,0,0,0), 1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,3,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,8,3,0,0,0), 1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,3,0,0,0)}, + + // Subtract 1 day, from one day after DST transition + {"America/Los_Angeles", CalFields(2014,3,10,1,59,59,999), -1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,1,59,59,999)}, + + {"America/Los_Angeles", CalFields(2014,3,10,1,59,59,999), -1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,1,59,59,999)}, + + {"America/Los_Angeles", CalFields(2014,3,10,1,59,59,999), -1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,1,59,59,999)}, + + + {"America/Los_Angeles", CalFields(2014,3,10,2,0,0,0), -1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,1,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,10,2,0,0,0), -1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,3,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,10,2,0,0,0), -1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,3,0,0,0)}, + + + {"America/Los_Angeles", CalFields(2014,3,10,2,30,0,0), -1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,1,30,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,10,2,30,0,0), -1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,3,30,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,10,2,30,0,0), -1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,3,0,0,0)}, + + + {"America/Los_Angeles", CalFields(2014,3,10,3,0,0,0), -1, UCAL_WALLTIME_FIRST, + CalFields(2014,3,9,3,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,10,3,0,0,0), -1, UCAL_WALLTIME_LAST, + CalFields(2014,3,9,3,0,0,0)}, + + {"America/Los_Angeles", CalFields(2014,3,10,3,0,0,0), -1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2014,3,9,3,0,0,0)}, + + + // Test case for ticket#10544 + {"America/Santiago", CalFields(2013,4,27,0,0,0,0), 134, UCAL_WALLTIME_FIRST, + CalFields(2013,9,7,23,0,0,0)}, + + {"America/Santiago", CalFields(2013,4,27,0,0,0,0), 134, UCAL_WALLTIME_LAST, + CalFields(2013,9,8,1,0,0,0)}, + + {"America/Santiago", CalFields(2013,4,27,0,0,0,0), 134, UCAL_WALLTIME_NEXT_VALID, + CalFields(2013,9,8,1,0,0,0)}, + + + {"America/Santiago", CalFields(2013,4,27,0,30,0,0), 134, UCAL_WALLTIME_FIRST, + CalFields(2013,9,7,23,30,0,0)}, + + {"America/Santiago", CalFields(2013,4,27,0,30,0,0), 134, UCAL_WALLTIME_LAST, + CalFields(2013,9,8,1,30,0,0)}, + + {"America/Santiago", CalFields(2013,4,27,0,30,0,0), 134, UCAL_WALLTIME_NEXT_VALID, + CalFields(2013,9,8,1,0,0,0)}, + + + // Extreme transition - Pacific/Apia completely skips 2011-12-30 + {"Pacific/Apia", CalFields(2011,12,29,0,0,0,0), 1, UCAL_WALLTIME_FIRST, + CalFields(2011,12,31,0,0,0,0)}, + + {"Pacific/Apia", CalFields(2011,12,29,0,0,0,0), 1, UCAL_WALLTIME_LAST, + CalFields(2011,12,31,0,0,0,0)}, + + {"Pacific/Apia", CalFields(2011,12,29,0,0,0,0), 1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2011,12,31,0,0,0,0)}, + + + {"Pacific/Apia", CalFields(2011,12,31,12,0,0,0), -1, UCAL_WALLTIME_FIRST, + CalFields(2011,12,29,12,0,0,0)}, + + {"Pacific/Apia", CalFields(2011,12,31,12,0,0,0), -1, UCAL_WALLTIME_LAST, + CalFields(2011,12,29,12,0,0,0)}, + + {"Pacific/Apia", CalFields(2011,12,31,12,0,0,0), -1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2011,12,29,12,0,0,0)}, + + + // 30 minutes DST - Australia/Lord_Howe + {"Australia/Lord_Howe", CalFields(2013,10,5,2,15,0,0), 1, UCAL_WALLTIME_FIRST, + CalFields(2013,10,6,1,45,0,0)}, + + {"Australia/Lord_Howe", CalFields(2013,10,5,2,15,0,0), 1, UCAL_WALLTIME_LAST, + CalFields(2013,10,6,2,45,0,0)}, + + {"Australia/Lord_Howe", CalFields(2013,10,5,2,15,0,0), 1, UCAL_WALLTIME_NEXT_VALID, + CalFields(2013,10,6,2,30,0,0)}, + + {NULL, CalFields(0,0,0,0,0,0,0), 0, UCAL_WALLTIME_LAST, CalFields(0,0,0,0,0,0,0)} +}; + +void CalendarTest::TestAddAcrossZoneTransition() { + UErrorCode status = U_ZERO_ERROR; + GregorianCalendar cal(status); + TEST_CHECK_STATUS; + + for (int32_t i = 0; AAZTDATA[i].zone; i++) { + status = U_ZERO_ERROR; + TimeZone *tz = TimeZone::createTimeZone(AAZTDATA[i].zone); + cal.adoptTimeZone(tz); + cal.setSkippedWallTimeOption(AAZTDATA[i].skippedWTOpt); + AAZTDATA[i].base.setTo(cal); + cal.add(UCAL_DATE, AAZTDATA[i].deltaDays, status); + TEST_CHECK_STATUS; + + if (!AAZTDATA[i].expected.isEquivalentTo(cal, status)) { + CalFields res(cal, status); + TEST_CHECK_STATUS; + char buf[32]; + const char *optDisp = AAZTDATA[i].skippedWTOpt == UCAL_WALLTIME_FIRST ? "FIRST" : + AAZTDATA[i].skippedWTOpt == UCAL_WALLTIME_LAST ? "LAST" : "NEXT_VALID"; + errln(UnicodeString("Error: base:") + AAZTDATA[i].base.toString(buf, sizeof(buf)) + ", tz:" + AAZTDATA[i].zone + + ", delta:" + AAZTDATA[i].deltaDays + " day(s), opt:" + optDisp + + ", result:" + res.toString(buf, sizeof(buf)) + + " - expected:" + AAZTDATA[i].expected.toString(buf, sizeof(buf))); + } + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ //eof diff --git a/icuSources/test/intltest/caltest.h b/icuSources/test/intltest/caltest.h index 97408df5..09c28964 100644 --- a/icuSources/test/intltest/caltest.h +++ b/icuSources/test/intltest/caltest.h @@ -1,5 +1,5 @@ /*********************************************************************** - * Copyright (c) 1997-2012, International Business Machines Corporation + * Copyright (c) 1997-2014, International Business Machines Corporation * and others. All Rights Reserved. ***********************************************************************/ @@ -237,6 +237,8 @@ public: // package void TestSkippedWallTime(void); void TestCloneLocale(void); + + void TestAddAcrossZoneTransition(void); }; #endif /* #if !UCONFIG_NO_FORMATTING */