/******************************************************************************* * Copyright © 2006, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.javart.util; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; import java.util.Locale; import com.ibm.icu.text.DateFormat; import com.ibm.icu.text.DateFormatSymbols; import com.ibm.icu.util.*; /** * This class has constants and utility methods related to date/time values. * * @author mheitz */ public class DateTimeUtil { /** * The value of TimeZone.getDefault(). */ public static final java.util.TimeZone DEFAULT_TIME_ZONE = java.util.TimeZone.getDefault(); /** * The ICU4J version of DEFAULT_TIME_ZONE. */ private static final TimeZone DEFAULT_ICU_TIME_ZONE = TimeZone.getTimeZone( DEFAULT_TIME_ZONE.getID(), TimeZone.TIMEZONE_JDK ); /** * The number of microseconds in a second (one million). */ public static final int MICROSECONDS_PER_SECOND = 1000000; /** * SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY = 86400 */ public static final int SECONDS_PER_DAY = 86400; /** * This is used by getNewCalendar. */ private static final Calendar baseCalendar; static { // Initialize baseCalendar. baseCalendar = Calendar.getInstance( DEFAULT_TIME_ZONE ); baseCalendar.clear(); baseCalendar.setLenient( false ); } /** * Returns a new instance of a Calendar, set to the current time. It will * not be lenient. * * @return a new instance of a Calendar. */ public static Calendar getNewCalendar() { // Cloning an existing Calendar is faster than calling // Calendar.getInstance() and then setLenient( false ). Calendar cal = (Calendar)baseCalendar.clone(); cal.setTimeInMillis( System.currentTimeMillis() ); return cal; } public static Calendar getNewCalendar(Date date) { Calendar cal = getNewCalendar(); cal.setTime(date); return cal; } public static Calendar getNewCalendar(java.sql.Date date) { Calendar cal = null; if(date != null){ cal = getNewCalendar(); cal.setTime(date); } return cal; } public static Calendar getNewCalendar(Time time) { Calendar cal = null; if(time != null){ cal = getNewCalendar(); cal.setTime(time); } return cal; } public static Calendar getNewCalendar(Timestamp timestamp) { Calendar cal = null; if(timestamp != null){ cal = getNewCalendar(); cal.setTime(timestamp); } return cal; } /** * This is like getNewCalendar but the calendar isn't set to the current time. * * @return a new calendar. */ public static Calendar getBaseCalendar() { return (Calendar)baseCalendar.clone(); } /** * Indicates a type of calendar. Used to index the DATE_FORMAT arrays. */ private static final int GREGORIAN = 0; /** * Indicates a type of calendar. Used to index the DATE_FORMAT arrays. */ private static final int BUDDHIST = 1; /** * Indicates a type of calendar. Used to index the DATE_FORMAT arrays. */ private static final int CHINESE = 2; /** * Indicates a type of calendar. Used to index the DATE_FORMAT arrays. */ private static final int HEBREW = 3; /** * Indicates a type of calendar. Used to index the DATE_FORMAT arrays. */ private static final int ISLAMIC = 4; /** * Indicates a type of calendar. Used to index the DATE_FORMAT arrays. */ private static final int JAPANESE = 5; /** * The DateFormat objects. There's one for each type of calendar. */ private static JavartDateFormat[] DATE_FORMATTERS = new JavartDateFormat[ 6 ]; /** * A place to keep track of the Locale used to create each JavartDateFormat in * DATE_FORMATTERS. */ private static Locale[] DATE_FORMATTER_LOCALES = new Locale[ 6 ]; /** * A field provided for synchronization of calls to getDateFormat. */ public static final byte[] LOCK = new byte[ 0 ]; /** * Returns a formatter for the date-time format pattern. Its applyPattern * method will be called. * <P> * <B>*** IMPORTANT ***</B> Call this method and use the formatter within a * synchronized block that synchronizes on DateTimeUtil.LOCK. Or, if the * formatter will be used extensively, clone it before leaving the * synchronized block. * * @param pattern the pattern. * @return a formatter for the pattern. */ public static JavartDateFormat getDateFormat( String pattern ) { // Determine the calendar type. int type = GREGORIAN; boolean calendarSpecified = false; if ( pattern.length() > 1 ) { switch ( pattern.charAt( 0 ) ) { case 'B': if ( pattern.charAt( 1 ) == 'u' ) { type = BUDDHIST; calendarSpecified = true; } break; case 'C': if ( pattern.charAt( 1 ) == 'h' ) { type = CHINESE; calendarSpecified = true; } break; case 'G': if ( pattern.charAt( 1 ) == 'r' ) { // GREGORIAN calendarSpecified = true; } break; case 'H': if ( pattern.charAt( 1 ) == 'e' ) { type = HEBREW; calendarSpecified = true; } break; case 'I': if ( pattern.charAt( 1 ) == 's' ) { type = ISLAMIC; calendarSpecified = true; } break; case 'J': if ( pattern.charAt( 1 ) == 'a' ) { type = JAPANESE; calendarSpecified = true; } break; } } // If there's a calendar specifier in the pattern, remove it. if ( calendarSpecified ) { pattern = pattern.substring( 2 ); } // Get the formatter. Create one if we haven't made one yet, or we made // one with a different Locale. JavartDateFormat formatter = DATE_FORMATTERS[ type ]; Locale locale = Locale.getDefault(); if ( formatter == null || !locale.equals( DATE_FORMATTER_LOCALES[ type ] ) ) { // Need to create the formatter. com.ibm.icu.util.Calendar cal = null; switch ( type ) { case GREGORIAN: cal = new GregorianCalendar( locale ) { protected DateFormat handleGetDateFormat( String pattern, String override, ULocale locale ) { DateFormatSymbols symbols = new DateFormatSymbols( this, locale ); return new JavartSimpleDateFormat( pattern, symbols, locale ); } protected DateFormat handleGetDateFormat( String pattern, ULocale locale ) { return handleGetDateFormat( pattern, null, locale ); } protected DateFormat handleGetDateFormat( String pattern, String override, Locale locale ) { return handleGetDateFormat( pattern, override, ULocale.forLocale( locale ) ); } protected DateFormat handleGetDateFormat( String pattern, Locale locale ) { return handleGetDateFormat( pattern, null, ULocale.forLocale( locale ) ); } }; break; case BUDDHIST: cal = new BuddhistCalendar( locale ) { protected DateFormat handleGetDateFormat( String pattern, String override, ULocale locale ) { DateFormatSymbols symbols = new DateFormatSymbols( this, locale ); return new JavartSimpleDateFormat( pattern, symbols, locale ); } protected DateFormat handleGetDateFormat( String pattern, ULocale locale ) { return handleGetDateFormat( pattern, null, locale ); } protected DateFormat handleGetDateFormat( String pattern, String override, Locale locale ) { return handleGetDateFormat( pattern, override, ULocale.forLocale( locale ) ); } protected DateFormat handleGetDateFormat( String pattern, Locale locale ) { return handleGetDateFormat( pattern, null, ULocale.forLocale( locale ) ); } }; break; case CHINESE: cal = new ChineseCalendar() { protected DateFormat handleGetDateFormat( String pattern, String override, ULocale locale ) { return new JavartChineseDateFormat( pattern, locale ); } protected DateFormat handleGetDateFormat( String pattern, ULocale locale ) { return handleGetDateFormat( pattern, null, locale ); } protected DateFormat handleGetDateFormat( String pattern, String override, Locale locale ) { return handleGetDateFormat( pattern, override, ULocale.forLocale( locale ) ); } protected DateFormat handleGetDateFormat( String pattern, Locale locale ) { return handleGetDateFormat( pattern, null, ULocale.forLocale( locale ) ); } }; break; case HEBREW: cal = new HebrewCalendar( locale ) { protected DateFormat handleGetDateFormat( String pattern, String override, ULocale locale ) { DateFormatSymbols symbols = new DateFormatSymbols( this, locale ); return new JavartSimpleDateFormat( pattern, symbols, locale ); } protected DateFormat handleGetDateFormat( String pattern, ULocale locale ) { return handleGetDateFormat( pattern, null, locale ); } protected DateFormat handleGetDateFormat( String pattern, String override, Locale locale ) { return handleGetDateFormat( pattern, override, ULocale.forLocale( locale ) ); } protected DateFormat handleGetDateFormat( String pattern, Locale locale ) { return handleGetDateFormat( pattern, null, ULocale.forLocale( locale ) ); } }; break; case ISLAMIC: cal = new IslamicCalendar( locale ) { protected DateFormat handleGetDateFormat( String pattern, String override, ULocale locale ) { DateFormatSymbols symbols = new DateFormatSymbols( this, locale ); return new JavartSimpleDateFormat( pattern, symbols, locale ); } protected DateFormat handleGetDateFormat( String pattern, ULocale locale ) { return handleGetDateFormat( pattern, null, locale ); } protected DateFormat handleGetDateFormat( String pattern, String override, Locale locale ) { return handleGetDateFormat( pattern, override, ULocale.forLocale( locale ) ); } protected DateFormat handleGetDateFormat( String pattern, Locale locale ) { return handleGetDateFormat( pattern, null, ULocale.forLocale( locale ) ); } }; break; case JAPANESE: cal = new JapaneseCalendar( locale ) { protected DateFormat handleGetDateFormat( String pattern, String override, ULocale locale ) { DateFormatSymbols symbols = new DateFormatSymbols( this, locale ); return new JavartSimpleDateFormat( pattern, symbols, locale ); } protected DateFormat handleGetDateFormat( String pattern, ULocale locale ) { return handleGetDateFormat( pattern, null, locale ); } protected DateFormat handleGetDateFormat( String pattern, String override, Locale locale ) { return handleGetDateFormat( pattern, override, ULocale.forLocale( locale ) ); } protected DateFormat handleGetDateFormat( String pattern, Locale locale ) { return handleGetDateFormat( pattern, null, ULocale.forLocale( locale ) ); } }; break; } cal.setTimeZone( DEFAULT_ICU_TIME_ZONE ); formatter = (JavartDateFormat)cal.getDateTimeFormat( DateFormat.DEFAULT, DateFormat.DEFAULT, ULocale.forLocale( locale ) ); formatter.setLenient( false ); DATE_FORMATTERS[ type ] = formatter; DATE_FORMATTER_LOCALES[ type ] = locale; } // Apply the pattern and return. formatter.applyPattern( pattern ); return formatter; } }