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