1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2004-2008, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 * 9 */ 10 11 package com.ibm.icu.dev.tool.timescale; 12 13 import java.util.Date; 14 import java.util.Locale; 15 16 import com.ibm.icu.text.MessageFormat; 17 import com.ibm.icu.util.Calendar; 18 import com.ibm.icu.util.GregorianCalendar; 19 import com.ibm.icu.util.SimpleTimeZone; 20 import com.ibm.icu.util.TimeZone; 21 22 /** 23 * This tool calculates the numeric values of the epoch offsets 24 * used in UniversalTimeScale. 25 * 26 * @see com.ibm.icu.util.UniversalTimeScale 27 */ 28 public class EpochOffsets 29 { 30 31 /** 32 * The default constructor. 33 */ EpochOffsets()34 public EpochOffsets() 35 { 36 } 37 38 private static final long ticks = 1; 39 private static final long microseconds = ticks * 10; 40 private static final long milliseconds = microseconds * 1000; 41 private static final long seconds = milliseconds * 1000; 42 private static final long minutes = seconds * 60; 43 private static final long hours = minutes * 60; 44 private static final long days = hours * 24; 45 // Java measures time in milliseconds, not in 100ns ticks. 46 private static final long javaDays = days / milliseconds; 47 48 private static int[][] epochDates = { 49 { 1, Calendar.JANUARY, 1}, 50 {1970, Calendar.JANUARY, 1}, 51 {1601, Calendar.JANUARY, 1}, 52 {1904, Calendar.JANUARY, 1}, 53 {2001, Calendar.JANUARY, 1}, 54 {1899, Calendar.DECEMBER, 31}, 55 {1900, Calendar.MARCH, 1} 56 }; 57 58 /** 59 * The <code>main()</code> method calculates the epoch offsets used by the 60 * <code>UniversalTimeScale</code> class. 61 * 62 * The calculations are done using an ICU <code>Calendar</code> object. The first step is 63 * to calculate the Universal Time Scale's epoch date. Then the epoch offsets are calculated 64 * by calculating each epoch date, subtracting the universal epoch date from it, and converting 65 * that value to ticks. 66 * 67 * @param args - the command line arguments. 68 */ main(String[] args)69 public static void main(String[] args) 70 { 71 TimeZone utc = new SimpleTimeZone(0, "UTC"); 72 73 // Jitterbug 5211: .Net System.DateTime uses the proleptic calendar, 74 // while ICU by default uses the Julian calendar before 1582. 75 // Original code: Calendar cal = Calendar.getInstance(utc, Locale.ENGLISH); 76 // Use a proleptic Gregorian calendar for 0001AD and later by setting 77 // the Gregorian change date before 0001AD with a value 78 // that is safely before that date by any measure, i.e., 79 // more than 719164 days before 1970. 80 long before0001AD = -1000000 * javaDays; 81 GregorianCalendar cal = new GregorianCalendar(utc, Locale.ENGLISH); 82 cal.setGregorianChange(new Date(before0001AD)); 83 84 MessageFormat fmt = new MessageFormat("{0, date, full} {0, time, full} = {1}"); 85 Object arguments[] = {cal, null}; 86 87 System.out.println("Epoch offsets:"); 88 89 // January 1, 0001 00:00:00 is the universal epoch date... 90 cal.set(1, Calendar.JANUARY, 1, 0, 0, 0); 91 92 long universalEpoch = cal.getTimeInMillis(); 93 94 for (int i = 0; i < epochDates.length; i += 1) { 95 int[] date = epochDates[i]; 96 97 cal.set(date[0], date[1], date[2]); 98 99 long millis = cal.getTimeInMillis(); 100 101 arguments[1] = Long.toString((millis - universalEpoch) * milliseconds); 102 103 System.out.println(fmt.format(arguments)); 104 } 105 } 106 } 107