/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.gwt.widgets.client.utils; import org.pentaho.gwt.widgets.client.i18n.WidgetsLocalizedMessages; import org.pentaho.gwt.widgets.client.i18n.WidgetsLocalizedMessagesSingleton; import java.util.Date; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import com.google.gwt.i18n.client.DateTimeFormat; public class TimeUtil { private static final WidgetsLocalizedMessages MSGS = WidgetsLocalizedMessagesSingleton.getInstance().getMessages(); public static final int HOURS_IN_DAY = 24; public static final int MINUTES_IN_HOUR = 60; public static final int SECONDS_IN_MINUTE = 60; public static final int MILLISECS_IN_SECONDS = 1000; public static final int MIN_HOUR = 0; public static final int MAX_HOUR = HOURS_IN_DAY / 2; public static final int MAX_MINUTE = 60; public static final int MAX_SECOND_BY_MILLISEC = Integer.MAX_VALUE / MILLISECS_IN_SECONDS; public static final int MAX_MINUTE_BY_MILLISEC = MAX_SECOND_BY_MILLISEC / SECONDS_IN_MINUTE; public static final int MAX_HOUR_BY_MILLISEC = MAX_MINUTE_BY_MILLISEC / MINUTES_IN_HOUR; public enum TimeOfDay { AM( 0, MSGS.am() ), PM( 1, MSGS.pm() ); TimeOfDay( int value, String name ) { this.value = value; this.name = name; } private final int value; private final String name; private static TimeOfDay[] timeOfDay = { AM, PM }; public int value() { return value; } public String toString() { return name; } public static TimeOfDay get( int idx ) { return timeOfDay[idx]; } public static int length() { return timeOfDay.length; } public static TimeOfDay stringToTimeOfDay( String timeOfDay ) throws EnumException { for ( TimeOfDay v : EnumSet.range( TimeOfDay.AM, TimeOfDay.PM ) ) { if ( v.toString().equalsIgnoreCase( timeOfDay ) ) { return v; } } throw new EnumException( MSGS.invalidStringForTimeOfDay( timeOfDay ) ); } } // end enum TimeOfDay /** * Names of enum are used as key in resource bundle. */ public enum DayOfWeek { SUN( 0, "sunday" ), MON( 1, "monday" ), TUE( 2, "tuesday" ), WED( 3, "wednesday" ), THU( 4, "thursday" ), FRI( 5, "friday" ), SAT( 6, "saturday" ); DayOfWeek( int value, String name ) { this.value = value; this.name = name; } private final int value; private final String name; private static DayOfWeek[] week = { SUN, MON, TUE, WED, THU, FRI, SAT }; public int value() { return value; } public String toString() { return name; } public static DayOfWeek get( int idx ) { return week[idx]; } public static int length() { return week.length; } } /* end enum */ public enum MonthOfYear { JAN( 0, "january" ), FEB( 1, "february" ), MAR( 2, "march" ), APR( 3, "april" ), MAY( 4, "may" ), JUN( 5, "june" ), JUL( 6, "july" ), AUG( 7, "august" ), SEPT( 8, "september" ), OCT( 9, "october" ), NOV( 10, "november" ), DEC( 11, "december" ); MonthOfYear( int value, String name ) { this.value = value; this.name = name; } private final int value; private final String name; private static MonthOfYear[] year = { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEPT, OCT, NOV, DEC }; public int value() { return value; } public String toString() { return name; } public static MonthOfYear get( int idx ) { return year[idx]; } public static int length() { return year.length; } } /* end enum */ public enum WeekOfMonth { FIRST( 0, "first_num" ), SECOND( 1, "second_num" ), THIRD( 2, "third_num" ), FOURTH( 3, "fourth_num" ), LAST( 4, "last_num" ); WeekOfMonth( int value, String name ) { this.value = value; this.name = name; } private final int value; private final String name; private static WeekOfMonth[] week = { FIRST, SECOND, THIRD, FOURTH, LAST }; public int value() { return value; } public String toString() { return name; } public static WeekOfMonth get( int idx ) { return week[idx]; } public static int length() { return week.length; } public static WeekOfMonth stringToWeekOfMonth( String weekOfMonth ) throws EnumException { for ( WeekOfMonth v : EnumSet.range( WeekOfMonth.FIRST, WeekOfMonth.LAST ) ) { if ( v.toString().equals( weekOfMonth ) ) { return v; } } throw new EnumException( MSGS.invalidStringForWeekOfMonth( weekOfMonth ) ); } } // end enum WeekOfMonth private static Map<MonthOfYear, Integer> validNumDaysOfMonth = new HashMap<MonthOfYear, Integer>(); static { validNumDaysOfMonth.put( MonthOfYear.JAN, 31 ); validNumDaysOfMonth.put( MonthOfYear.FEB, 29 ); validNumDaysOfMonth.put( MonthOfYear.MAR, 31 ); validNumDaysOfMonth.put( MonthOfYear.APR, 30 ); validNumDaysOfMonth.put( MonthOfYear.MAY, 31 ); validNumDaysOfMonth.put( MonthOfYear.JUN, 30 ); validNumDaysOfMonth.put( MonthOfYear.JUL, 31 ); validNumDaysOfMonth.put( MonthOfYear.AUG, 31 ); validNumDaysOfMonth.put( MonthOfYear.SEPT, 30 ); validNumDaysOfMonth.put( MonthOfYear.OCT, 31 ); validNumDaysOfMonth.put( MonthOfYear.NOV, 30 ); validNumDaysOfMonth.put( MonthOfYear.DEC, 31 ); } private TimeUtil() { } // cannot create instance, static class public static long daysToSecs( long days ) { return hoursToSecs( days * HOURS_IN_DAY ); } public static long hoursToSecs( long hours ) { return minutesToSecs( hours * MINUTES_IN_HOUR ); } public static long minutesToSecs( long minutes ) { return minutes * SECONDS_IN_MINUTE; } public static long secsToMillisecs( long secs ) { return secs * MILLISECS_IN_SECONDS; } public static long secsToDays( long secs ) { return secs / HOURS_IN_DAY / MINUTES_IN_HOUR / SECONDS_IN_MINUTE; } public static long secsToHours( long secs ) { return secs / MINUTES_IN_HOUR / SECONDS_IN_MINUTE; } public static long secsToMinutes( long secs ) { return secs / SECONDS_IN_MINUTE; } public static boolean isSecondsWholeDay( long secs ) { return ( daysToSecs( secsToDays( secs ) ) ) == secs; } public static boolean isSecondsWholeHour( long secs ) { return ( hoursToSecs( secsToHours( secs ) ) ) == secs; } public static boolean isSecondsWholeMinute( long secs ) { return ( minutesToSecs( secsToMinutes( secs ) ) ) == secs; } /** * Time of day is element of {AM, PM} * * @param hour * @return */ public static TimeOfDay getTimeOfDayBy0To23Hour( String hour ) { return getTimeOfDayBy0To23Hour( Integer.parseInt( hour ) ); } public static TimeOfDay getTimeOfDayBy0To23Hour( int hour ) { return hour < MAX_HOUR ? TimeOfDay.AM : TimeOfDay.PM; } /** * Convert a 24 hour time, where hours are 0-23, to a twelve hour time, where 0-23 maps to 0...11 AM and 0...11 PM * * @param int0To23hour * int integer in the range 0..23 * @return int integer in the range 0..11 */ public static int to12HourClock( int int0To23hour ) { assert int0To23hour >= 0 && int0To23hour <= 23 : "int0To23hour is out of range"; //$NON-NLS-1$ int int0To11 = int0To23hour < MAX_HOUR ? int0To23hour : int0To23hour - MAX_HOUR; return int0To11; } /** * @param time * String it will look like: '17:17:00 PM' for 5:17 PM */ public static String to12HourClock( String time ) { String[] parts = time.split( ":" ); //$NON-NLS-1$ int hour = Integer.parseInt( parts[0] ); if ( hour > MAX_HOUR ) { hour -= MAX_HOUR; } if ( hour == 0 ) { hour = MAX_HOUR; } return Integer.toString( hour ) + ":" + parts[1] + ":" + parts[2]; //$NON-NLS-1$//$NON-NLS-2$ } /** * map 0..11 to 12,1..11 */ public static int map0Through11To12Through11( int int0To11 ) { return int0To11 == 0 ? 12 : int0To11; } // NOTE: this method will produce rounding errors, since it doesn't round, it truncates public static long millsecondsToSecs( long milliseconds ) { return milliseconds / MILLISECS_IN_SECONDS; } /** * TODO sbarkdull, gwt 1.5 has a DateTimeFormatter, change this method to use it. * * sample output: May 21, 2008 8:29:21 PM This is consistent with the formatter constructed like this: DateFormat * formatter = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, Locale.getDefault()); */ public static String getDateTimeString( String month, String dayInMonth, String year, String hour, String minute, String second, TimeOfDay timeOfDay ) { return new StringBuilder().append( getDateString( month, dayInMonth, year ) ).append( " " ) .append( hour ).append( ":" ) .append( minute ).append( ":" ) .append( second ).append( " " ) .append( timeOfDay.toString() ).toString(); } // this code runs in a single thread, so it is ok to share these two DateTimeFormats private static DateTimeFormat dateFormatter = DateTimeFormat.getFormat( MSGS.dateFormat() ); private static DateTimeFormat dateTimeFormatter = DateTimeFormat.getFormat( MSGS.dateFormatLongMedium() ); public static Date getDateTime( String time, Date date ) { String strDate = dateFormatter.format( date ); return dateTimeFormatter.parse( strDate + " " + time ); //$NON-NLS-1$ } /** * * @param strDate * String representing the date, in this format: MMM dd, yyyy HH:mm:ss a * @return */ public static Date getDate( String strDate ) { return dateTimeFormatter.parse( strDate ); } /** * Get the time part of a date string. * * @param dateTime * String in this format: MMM dd, yyyy HH:mm:ss a * @return String HH:mm:ss a */ public static String getTimePart( String dateTime ) { String[] parts = dateTime.split( "\\s" ); //$NON-NLS-1$ // TODO sbarkdull, use StringBuilder return parts[3] + " " + parts[4]; //$NON-NLS-1$ } /** * Get the time part of a date string. * * @param dateTime * Date * @return String HH:mm:ss a */ public static String getTimePart( Date dateTime ) { String strDateTime = dateTimeFormatter.format( dateTime ); return to12HourClock( getTimePart( strDateTime ) ); } /** * Get the time part of a date string. * * @param dateTime * String in this format: MMM dd, yyyy HH:mm:ss a * @return String HH:mm:ss a */ public static String getDatePart( String dateTime ) { String[] parts = dateTime.split( "\\s" ); //$NON-NLS-1$ // TODO sbarkdull, use StringBuilder return parts[0] + " " + parts[1] + " " + parts[2]; //$NON-NLS-1$ //$NON-NLS-2$ } public static String get0thTime() { // TODO sbarkdull, use StringBuilder return "12:00:00 " + TimeOfDay.AM.toString(); //$NON-NLS-1$ } public static String zeroTimePart( String dateTime ) { // TODO sbarkdull, use StringBuilder return getDatePart( dateTime ) + " " + get0thTime(); //$NON-NLS-1$ } public static Date zeroTimePart( Date dateTime ) { // TODO sbarkdull, use StringBuilder Date newDate = (Date) dateTime.clone(); newDate.setHours( 0 ); newDate.setSeconds( 0 ); newDate.setMinutes( 0 ); return newDate; } /** * TODO sbarkdull, gwt 1.5 has a DateTimeFormatter, change this method to use it. * * sample output: May 21, 2008 This is consistent with the formatter constructed like this: DateFormat formatter = * DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault()); */ public static String getDateString( String month, String dayInMonth, String year ) { return new StringBuilder().append( month ).append( " " ) //$NON-NLS-1$ .append( dayInMonth ).append( ", " ) //$NON-NLS-1$ .append( year ).toString(); } public static boolean isValidNumOfDaysForMonth( int numDays, MonthOfYear month ) { if ( numDays < 1 ) { return false; } else { return validNumDaysOfMonth.get( month ) <= numDays; } } /** * Is <param>num</param> between <param>low</param> and <param>high</param>, inclusive. * * @param low * @param num * @param high * @return boolean true if <param>num</param> between <param>low</param> and <param>high</param>, inclusive, else * false. */ private static boolean isNumBetween( long low, long num, long high ) { return num >= low && num <= high; } public static boolean isDayOfMonth( int num ) { return isNumBetween( 1, num, 31 ); } public static boolean isDayOfWeek( int num ) { return isNumBetween( 1, num, 7 ); } public static boolean isWeekOfMonth( int num ) { return isNumBetween( 1, num, 4 ); } public static boolean isMonthOfYear( int num ) { return isNumBetween( 1, num, 12 ); } public static boolean isSecond( int num ) { return isNumBetween( 0, num, 59 ); } public static boolean isMinute( int num ) { return isNumBetween( 0, num, 59 ); } public static boolean isHour( int num ) { return isNumBetween( 0, num, 23 ); } // private static final String MATCH_DATE_STRING_RE = "^[0-9]{1,2}$"; // public boolean isDateStr( String strInt ) { // return MATCH_DATE_STRING_RE.matches( strInt ); // } public static void main( String[] args ) { assert daysToSecs( 13 ) == 1123200 : ""; //$NON-NLS-1$ assert daysToSecs( 13 ) != 1123201 : ""; //$NON-NLS-1$ assert daysToSecs( 13 ) != 1123199 : ""; //$NON-NLS-1$ assert hoursToSecs( 13 ) == 46800 : ""; //$NON-NLS-1$ assert hoursToSecs( 13 ) != 46801 : ""; //$NON-NLS-1$ assert hoursToSecs( 13 ) != 46799 : ""; //$NON-NLS-1$ assert minutesToSecs( 13 ) == 780 : ""; //$NON-NLS-1$ assert minutesToSecs( 13 ) != 781 : ""; //$NON-NLS-1$ assert minutesToSecs( 13 ) != 779 : ""; //$NON-NLS-1$ assert secsToDays( 1123200 ) == 13 : ""; //$NON-NLS-1$ assert secsToDays( 1123201 ) != 13 : ""; //$NON-NLS-1$ assert secsToDays( 1123199 ) != 13 : ""; //$NON-NLS-1$ assert secsToHours( 46800 ) == 13 : ""; //$NON-NLS-1$ assert secsToHours( 46801 ) != 13 : ""; //$NON-NLS-1$ assert secsToHours( 46799 ) != 13 : ""; //$NON-NLS-1$ assert secsToMinutes( 780 ) == 13 : ""; //$NON-NLS-1$ assert secsToMinutes( 781 ) != 13 : ""; //$NON-NLS-1$ assert secsToMinutes( 779 ) != 13 : ""; //$NON-NLS-1$ assert isSecondsWholeDay( 1123200 ) : ""; //$NON-NLS-1$ assert !isSecondsWholeDay( 1123201 ) : ""; //$NON-NLS-1$ assert !isSecondsWholeDay( 1123199 ) : ""; //$NON-NLS-1$ assert isSecondsWholeHour( 46800 ) : ""; //$NON-NLS-1$ assert !isSecondsWholeHour( 46801 ) : ""; //$NON-NLS-1$ assert !isSecondsWholeHour( 46799 ) : ""; //$NON-NLS-1$ assert isSecondsWholeMinute( 780 ) : ""; //$NON-NLS-1$ assert !isSecondsWholeMinute( 781 ) : ""; //$NON-NLS-1$ assert !isSecondsWholeMinute( 779 ) : ""; //$NON-NLS-1$ assert getTimeOfDayBy0To23Hour( "0" ) == TimeOfDay.AM : "hour 0 is AM"; //$NON-NLS-1$ //$NON-NLS-2$ assert getTimeOfDayBy0To23Hour( "11" ) == TimeOfDay.AM : "hour 11 is AM"; //$NON-NLS-1$ //$NON-NLS-2$ assert getTimeOfDayBy0To23Hour( "12" ) == TimeOfDay.PM : "hour 12 is PM"; //$NON-NLS-1$ //$NON-NLS-2$ assert getTimeOfDayBy0To23Hour( "13" ) == TimeOfDay.PM : "hour 13 is PM"; //$NON-NLS-1$ //$NON-NLS-2$ assert getTimeOfDayBy0To23Hour( "23" ) == TimeOfDay.PM : "hour 23 is PM"; //$NON-NLS-1$ //$NON-NLS-2$ assert to12HourClock( 0 ) == ( 1 ) : "0 is 1"; //$NON-NLS-1$ assert to12HourClock( 11 ) == ( 12 ) : "11 is 12"; //$NON-NLS-1$ assert to12HourClock( 12 ) == ( 1 ) : "12 is 1"; //$NON-NLS-1$ assert to12HourClock( 23 ) == ( 11 ) : "23 is 11"; //$NON-NLS-1$ System.out.println( "done" ); //$NON-NLS-1$ } }