]> git.saurik.com Git - apple/icu.git/commitdiff
ICU-511.32.tar.gz os-x-1093 v511.32
authorApple <opensource@apple.com>
Tue, 11 Mar 2014 22:52:33 +0000 (22:52 +0000)
committerApple <opensource@apple.com>
Tue, 11 Mar 2014 22:52:33 +0000 (22:52 +0000)
icuSources/data/misc/metaZones.txt
icuSources/data/misc/zoneinfo64.txt
icuSources/i18n/calendar.cpp
icuSources/i18n/unicode/calendar.h
icuSources/test/intltest/caltest.cpp
icuSources/test/intltest/caltest.h

index da466334a1b4093c6a7c02f8e69351db43860c5f..ac8dbd2ba0d4227544d18675f824035f1e895a25 100644 (file)
@@ -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",
             }
         }
index 0f8dc6c37ddda0954601f05cefefd694dc900081..85271c2dc256612b2d7d1a66ba46da78e5c5c6bf 100644 (file)
@@ -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
index 4edd26104e9eb1e8e1590286113ed17275e58fce..88730a2ccb3873bc3ae523de1f81746f585bd4f9 100644 (file)
@@ -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
     // <April 30>, rather than <April 31> => <May 1>.
 
     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
index 6832939a450dd08cc350600e0b46abaf651e4605..24b0cbef64350cc905a6ceafc819b1d5be52d966 100644 (file)
@@ -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;
 };
 
 // -------------------------------------
index 5795160ce1da9c0827976b3cbd38da304741eec3..01f1407a06fcb351788f035c5df1d5b44a38ae18 100644 (file)
@@ -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
index 97408df5a36813fbe0a3b9c58a5871e6a76484c2..09c289642ddfecf0c48a817239f7e64eb7350a55 100644 (file)
@@ -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 */