1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2004-2010, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 * 9 */ 10 11 package com.ibm.icu.dev.test.timescale; 12 13 import java.util.Date; 14 import java.util.Locale; 15 16 import org.junit.Test; 17 import org.junit.runner.RunWith; 18 import org.junit.runners.JUnit4; 19 20 import com.ibm.icu.dev.test.TestFmwk; 21 import com.ibm.icu.util.GregorianCalendar; 22 import com.ibm.icu.util.SimpleTimeZone; 23 import com.ibm.icu.util.TimeZone; 24 import com.ibm.icu.util.UniversalTimeScale; 25 26 /** 27 * @author Owner 28 * 29 * TODO To change the template for this generated type comment go to 30 * Window - Preferences - Java - Code Style - Code Templates 31 */ 32 @RunWith(JUnit4.class) 33 public class TimeScaleDataTest extends TestFmwk 34 { 35 36 /** 37 * Default contstructor. 38 */ 39 public TimeScaleDataTest() 40 { 41 } 42 43 private void roundTripTest(long value, int scale) 44 { 45 long rt = UniversalTimeScale.toLong(UniversalTimeScale.from(value, scale), scale); 46 47 if (rt != value) { 48 errln("Round-trip error: time scale = " + scale + ", value = " + value + ", round-trip = " + rt); 49 } 50 } 51 52 private void toLimitTest(long toLimit, long fromLimit, int scale) 53 { 54 long result = UniversalTimeScale.toLong(toLimit, scale); 55 56 if (result != fromLimit) { 57 errln("toLimit failure: scale = " + scale + ", toLimit = " + toLimit + 58 ", toLong(toLimit, scale) = " + result + ", fromLimit = " + fromLimit); 59 } 60 } 61 62 private void epochOffsetTest(long epochOffset, long units, int scale) 63 { 64 long universalEpoch = epochOffset * units; 65 long local = UniversalTimeScale.toLong(universalEpoch, scale); 66 67 if (local != 0) { 68 errln("toLong(epochOffset, scale): scale = " + scale + ", epochOffset = " + universalEpoch + 69 ", result = " + local); 70 } 71 72 local = UniversalTimeScale.toLong(0, scale); 73 74 if (local != -epochOffset) { 75 errln("toLong(0, scale): scale = " + scale + ", result = " + local); 76 } 77 78 long universal = UniversalTimeScale.from(-epochOffset, scale); 79 80 if (universal != 0) { 81 errln("from(-epochOffest, scale): scale = " + scale + ", epochOffset = " + epochOffset + 82 ", result = " + universal); 83 } 84 85 universal = UniversalTimeScale.from(0, scale); 86 87 if (universal != universalEpoch) { 88 errln("from(0, scale): scale = " + scale + ", result = " + universal); 89 } 90 } 91 92 @Test 93 public void TestEpochOffsets() 94 { 95 for (int scale = 0; scale < UniversalTimeScale.MAX_SCALE; scale += 1) { 96 long units = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.UNITS_VALUE); 97 long epochOffset = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.EPOCH_OFFSET_VALUE); 98 99 epochOffsetTest(epochOffset, units, scale); 100 } 101 } 102 103 @Test 104 public void TestFromLimits() 105 { 106 for (int scale = 0; scale < UniversalTimeScale.MAX_SCALE; scale += 1) { 107 long fromMin = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.FROM_MIN_VALUE); 108 long fromMax = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.FROM_MAX_VALUE); 109 110 roundTripTest(fromMin, scale); 111 roundTripTest(fromMax, scale); 112 } 113 } 114 115 @Test 116 public void TestToLimits() 117 { 118 for (int scale = 0; scale < UniversalTimeScale.MAX_SCALE; scale += 1) { 119 long fromMin = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.FROM_MIN_VALUE); 120 long fromMax = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.FROM_MAX_VALUE); 121 long toMin = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.TO_MIN_VALUE); 122 long toMax = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.TO_MAX_VALUE); 123 124 toLimitTest(toMin, fromMin, scale); 125 toLimitTest(toMax, fromMax, scale); 126 } 127 } 128 129 // Test with data from .Net System.DateTime ---------------------------- *** 130 131 /* 132 * This data was generated by C++.Net code like 133 * Console::WriteLine(L" {{ {0}, 1, 1, INT64_C({1}) }},", year, DateTime(year, 1, 1).Ticks); 134 * with the DateTime constructor taking int values for year, month, and date. 135 */ 136 static private final long dotNetDateTimeTicks[] = { 137 /* year, month, day, ticks */ 138 100, 1, 1, 31241376000000000L, 139 100, 3, 1, 31292352000000000L, 140 200, 1, 1, 62798112000000000L, 141 200, 3, 1, 62849088000000000L, 142 300, 1, 1, 94354848000000000L, 143 300, 3, 1, 94405824000000000L, 144 400, 1, 1, 125911584000000000L, 145 400, 3, 1, 125963424000000000L, 146 500, 1, 1, 157469184000000000L, 147 500, 3, 1, 157520160000000000L, 148 600, 1, 1, 189025920000000000L, 149 600, 3, 1, 189076896000000000L, 150 700, 1, 1, 220582656000000000L, 151 700, 3, 1, 220633632000000000L, 152 800, 1, 1, 252139392000000000L, 153 800, 3, 1, 252191232000000000L, 154 900, 1, 1, 283696992000000000L, 155 900, 3, 1, 283747968000000000L, 156 1000, 1, 1, 315253728000000000L, 157 1000, 3, 1, 315304704000000000L, 158 1100, 1, 1, 346810464000000000L, 159 1100, 3, 1, 346861440000000000L, 160 1200, 1, 1, 378367200000000000L, 161 1200, 3, 1, 378419040000000000L, 162 1300, 1, 1, 409924800000000000L, 163 1300, 3, 1, 409975776000000000L, 164 1400, 1, 1, 441481536000000000L, 165 1400, 3, 1, 441532512000000000L, 166 1500, 1, 1, 473038272000000000L, 167 1500, 3, 1, 473089248000000000L, 168 1600, 1, 1, 504595008000000000L, 169 1600, 3, 1, 504646848000000000L, 170 1700, 1, 1, 536152608000000000L, 171 1700, 3, 1, 536203584000000000L, 172 1800, 1, 1, 567709344000000000L, 173 1800, 3, 1, 567760320000000000L, 174 1900, 1, 1, 599266080000000000L, 175 1900, 3, 1, 599317056000000000L, 176 2000, 1, 1, 630822816000000000L, 177 2000, 3, 1, 630874656000000000L, 178 2100, 1, 1, 662380416000000000L, 179 2100, 3, 1, 662431392000000000L, 180 2200, 1, 1, 693937152000000000L, 181 2200, 3, 1, 693988128000000000L, 182 2300, 1, 1, 725493888000000000L, 183 2300, 3, 1, 725544864000000000L, 184 2400, 1, 1, 757050624000000000L, 185 2400, 3, 1, 757102464000000000L, 186 2500, 1, 1, 788608224000000000L, 187 2500, 3, 1, 788659200000000000L, 188 2600, 1, 1, 820164960000000000L, 189 2600, 3, 1, 820215936000000000L, 190 2700, 1, 1, 851721696000000000L, 191 2700, 3, 1, 851772672000000000L, 192 2800, 1, 1, 883278432000000000L, 193 2800, 3, 1, 883330272000000000L, 194 2900, 1, 1, 914836032000000000L, 195 2900, 3, 1, 914887008000000000L, 196 3000, 1, 1, 946392768000000000L, 197 3000, 3, 1, 946443744000000000L, 198 1, 1, 1, 0L, 199 1601, 1, 1, 504911232000000000L, 200 1899, 12, 31, 599265216000000000L, 201 1904, 1, 1, 600527520000000000L, 202 1970, 1, 1, 621355968000000000L, 203 2001, 1, 1, 631139040000000000L, 204 9900, 3, 1, 3123873216000000000L, 205 9999, 12, 31, 3155378112000000000L 206 }; 207 208 /* 209 * ICU's Universal Time Scale is designed to be tick-for-tick compatible with 210 * .Net System.DateTime. Verify that this is so for the 211 * .Net-supported date range (years 1-9999 AD). 212 * This requires a proleptic Gregorian calendar because that's what .Net uses. 213 * Proleptic: No Julian/Gregorian switchover, or a switchover before 214 * any date that we test, that is, before 0001 AD. 215 */ 216 @Test 217 public void TestDotNet() { 218 TimeZone utc; 219 final long dayMillis = 86400 * 1000L; /* 1 day = 86400 seconds */ 220 final long dayTicks = 86400 * 10000000L; 221 final int kYear = 0; // offset for dotNetDateTimeTicks[] field 222 final int kMonth = 1; 223 final int kDay = 2; 224 final int kTicks = 3; 225 final int kIncrement = 4; 226 GregorianCalendar cal; 227 long icuDate; 228 long ticks, millis; 229 int i; 230 231 /* Open a proleptic Gregorian calendar. */ 232 long before0001AD = -1000000 * dayMillis; 233 utc = new SimpleTimeZone(0, "UTC"); 234 cal = new GregorianCalendar(utc, Locale.ENGLISH); 235 cal.setGregorianChange(new Date(before0001AD)); 236 for(i = 0; i < dotNetDateTimeTicks.length; i += kIncrement) { 237 /* Test conversion from .Net/Universal time to ICU time. */ 238 millis = UniversalTimeScale.toLong(dotNetDateTimeTicks[i + kTicks], UniversalTimeScale.ICU4C_TIME); 239 cal.clear(); 240 cal.set((int)dotNetDateTimeTicks[i + kYear], 241 (int)dotNetDateTimeTicks[i + kMonth] - 1, /* Java & ICU use January = month 0. */ 242 (int)dotNetDateTimeTicks[i + kDay]); 243 icuDate = cal.getTimeInMillis(); 244 if(millis != icuDate) { 245 /* Print days not millis. */ 246 errln("UniversalTimeScale.toLong(ticks[" + i + "], ICU4C)=" + 247 (millis/dayMillis) + " != " + (icuDate/dayMillis) + 248 "=ucal_getMillis(" + dotNetDateTimeTicks[i + kYear] + 249 "-" + dotNetDateTimeTicks[i + kMonth] + 250 "-" + dotNetDateTimeTicks[i + kDay] + ")"); 251 } 252 253 /* Test conversion from ICU time to .Net/Universal time. */ 254 ticks = UniversalTimeScale.from(icuDate, UniversalTimeScale.ICU4C_TIME); 255 if(ticks != dotNetDateTimeTicks[i + kTicks]) { 256 /* Print days not ticks. */ 257 errln("UniversalTimeScale.from(date[" + i + "], ICU4C)=" + 258 (ticks/dayTicks) + " != " + dotNetDateTimeTicks[i + kTicks]/dayTicks + 259 "=.Net System.DateTime(" + dotNetDateTimeTicks[i + kYear] + 260 "-" + dotNetDateTimeTicks[i + kMonth] + 261 "-" + dotNetDateTimeTicks[i + kDay] + ").Ticks"); 262 } 263 } 264 } 265 } 266