View Javadoc

1   /**
2    * Copyright 2013 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   * Created by Charles on 4/17/13
16   */
17  package org.kuali.student.r2.common.util;
18  
19  import org.kuali.student.r2.common.dto.TimeOfDayInfo;
20  import org.kuali.student.r2.common.exceptions.InvalidParameterException;
21  import org.kuali.student.r2.common.infc.TimeOfDay;
22  
23  import java.util.List;
24  
25  /**
26   * Formats and validates time (only accurate to the minute)
27   *
28   * @author Kuali Student Team
29   */
30  public class TimeOfDayHelper {
31      public static final long MILLIS_PER_MINUTE = 60000L;
32      public static final int MINUTES_PER_HOUR = 60;
33  
34      public static TimeOfDay createTimeOfDay(int normalHours, int minutes, TimeOfDayAmPmEnum amOrPm) throws InvalidParameterException {
35          if (normalHours < 1 || normalHours > 12 || minutes < 0 || minutes > 59) {
36              throw new InvalidParameterException("Invalid values for hours or minutes");
37          }
38         // Convert to military hours (0-23)
39          int milHours = normalHours;
40          if (amOrPm == TimeOfDayAmPmEnum.AM) {
41              if (normalHours == 12) {
42                  milHours = 0;
43              }
44          } else {
45              // is PM
46              if (normalHours != 12) {
47                  milHours += 12;
48              }
49          }
50          return createTimeOfDayInMilitary(milHours, minutes);
51      }
52  
53      public static TimeOfDay createTimeOfDayInMilitary(int milHours, int minutes) throws InvalidParameterException {
54          if (milHours < 0 || milHours > 23 || minutes < 0 || minutes > 59) {
55              throw new InvalidParameterException("Invalid values for military hours or minutes");
56          }
57  
58          // Now compute milliseconds
59          long millis = (milHours * MINUTES_PER_HOUR + minutes) * MILLIS_PER_MINUTE;
60          TimeOfDayInfo info = new TimeOfDayInfo();
61          info.setMilliSeconds(millis);
62          return info;
63      }
64  
65      public static String formatTimeOfDay(TimeOfDay timeOfDay) throws InvalidParameterException {
66          return formatTimeOfDay(timeOfDay, null);
67      }
68  
69      public static String formatTimeOfDay(TimeOfDay timeOfDay, List<TimeOfDayFormattingEnum> options) throws InvalidParameterException {
70          int hours = 0;
71          boolean isMilitary = false;
72          boolean skip = false;
73          if (options == null) {
74              skip = true;
75          }
76          if (!skip && options.contains(TimeOfDayFormattingEnum.USE_MILITARY_TIME)) {
77              isMilitary = true;
78              hours = getHoursInMilitaryTime(timeOfDay);
79          } else {
80              hours = getHours(timeOfDay);
81          }
82          String hoursStr = hours + "";
83          if (!skip && options.contains(TimeOfDayFormattingEnum.USE_TWO_DIGITS_FOR_HOURS) && hoursStr.length() < 2) {
84              hoursStr = "0" + hoursStr;
85          }
86          int minutes = getMinutes(timeOfDay);
87          String minutesStr = minutes + "";
88          if (minutesStr.length() < 2) {
89              minutesStr = "0" + minutesStr;
90          }
91          boolean isAM = isAM(timeOfDay);
92          String amOrPm = "";
93          if (!isMilitary) {
94              if (!skip && options.contains(TimeOfDayFormattingEnum.USE_ALL_CAPS_AM_PM)) {
95                  amOrPm = isAM ? "AM" : "PM";
96              } else if (!skip && options.contains(TimeOfDayFormattingEnum.USE_ALL_CAPS_AM_PM)) {
97                  amOrPm = isAM ? "Am" : "Pm";
98              } else {
99                  amOrPm = isAM ? "am" : "pm";
100             }
101             if (!skip && options.contains(TimeOfDayFormattingEnum.USE_ONLY_FIRST_LETTER_AM_PM)) {
102                 // Extract out the first letter
103                 amOrPm = amOrPm.substring(0, 1);
104             }
105         }
106         String formattedTime = hoursStr + ":" + minutesStr;
107         if (!isMilitary) {
108             formattedTime += " " + amOrPm;
109         }
110         return formattedTime;
111     }
112 
113     /**
114      * A non-mutating version that converts time of day to nearest minute (since it stores milliseconds).
115      * Note that it does truncation, not rounding.
116      * @param input A TimeOfDayInfo object
117      * @return A new TimeOfDayInfo object rounded to nearest minute
118      */
119     public static TimeOfDayInfo roundToNearestMinute(TimeOfDay input) {
120         if (input == null) {
121             return null;
122         }
123         long newMillis = (input.getMilliSeconds() / MILLIS_PER_MINUTE) * MILLIS_PER_MINUTE;
124         TimeOfDayInfo newInfo = new TimeOfDayInfo();
125         newInfo.setMilliSeconds(newMillis);
126         return newInfo;
127     }
128 
129     /**
130      * Returns hour of day in standard time (e.g. from 1-12).  Note that 1 PM and 1 AM would both return 1.
131      * @param timeOfDay A TimeOfDayInfo object
132      * @return Hours of day in standard time
133      * @throws InvalidParameterException If millis is null or negative or too big, then this exception is thrown.
134      */
135 
136     public static int getHours(TimeOfDay timeOfDay) throws InvalidParameterException {
137         int militaryHours = getHoursInMilitaryTime(timeOfDay); // Guarantees between 0-23 (or exception thrown)
138         int normalHours = 0;
139         if (militaryHours == 0) {
140             normalHours = 12; // midnight
141         } else if (militaryHours <= 12) {
142             normalHours = militaryHours;
143         } else {
144             normalHours = militaryHours - 12;
145         }
146         return normalHours;
147     }
148 
149     /**
150      * Returns hours from 0-23 in military time.
151      * @param timeOfDay A TimeOfDayInfo object
152      * @return Hours of day in military time
153      * @throws InvalidParameterException If millis is null or negative or too big, then this exception is thrown.
154      */
155     public static int getHoursInMilitaryTime(TimeOfDay timeOfDay) throws InvalidParameterException {
156         validateTimeOfDayInfo(timeOfDay);
157         long timeInMillis = timeOfDay.getMilliSeconds();
158         long hours = timeInMillis / (MILLIS_PER_MINUTE * MINUTES_PER_HOUR);
159         if (hours < 0 || hours > 23) {
160             throw new InvalidParameterException("Contains an invalid time of day");
161         }
162         return (int) hours;
163     }
164 
165     /**
166      * Returns hours from 0-59 representing the number of minutes after the hour (thus, 1:24 PM would return
167      * 24).
168      * @param timeOfDay A TimeOfDayInfo object
169      * @return Minutes after the hour
170      * @throws InvalidParameterException If millis is null or negative or too big, then this exception is thrown.
171      */
172     public static int getMinutes(TimeOfDay timeOfDay) throws InvalidParameterException {
173         validateTimeOfDayInfo(timeOfDay);
174         long timeInMillis = timeOfDay.getMilliSeconds();
175         int minutesInDay = (int) (timeInMillis / MILLIS_PER_MINUTE);
176         int minuteOffset = minutesInDay % MINUTES_PER_HOUR;
177         return minuteOffset;
178     }
179 
180     /**
181      * Returns true if time of day is AM, that is between midnight and 11:59 AM
182      * @param timeOfDay A TimeOfDayInfo object
183      * @return true, if time is AM.
184      * @throws InvalidParameterException If millis is null or negative or too big, then this exception is thrown.
185      */
186     public static boolean isAM(TimeOfDay timeOfDay) throws InvalidParameterException {
187         validateTimeOfDayInfo(timeOfDay);
188         int milHours = getHoursInMilitaryTime(timeOfDay);
189         return milHours < 12; // 0-11 is AM
190     }
191 
192     /**
193      * Returns true if time of day is PM, that is between noon and 11:59 PM
194      * @param timeOfDay A TimeOfDayInfo object
195      * @return true, if time is PM.
196      * @throws InvalidParameterException If millis is null or negative or too big, then this exception is thrown.
197      */
198     public static boolean isPM(TimeOfDay timeOfDay) throws InvalidParameterException {
199         return !isAM(timeOfDay);
200     }
201 
202     /**
203      * Validates by not throwing an exception
204      * @param timeOfDay A TimeOfDayInfo object
205      * @throws InvalidParameterException
206      */
207     public static void validateTimeOfDayInfo(TimeOfDay timeOfDay) throws InvalidParameterException {
208         if (timeOfDay == null) {
209             throw new InvalidParameterException("getMilliSeconds() is null");
210         }
211         Long timeInMillis = timeOfDay.getMilliSeconds();
212         if (timeInMillis < 0) {
213             throw new InvalidParameterException("getMilliSeconds() is negative");
214         }
215         Long threshold = 24 * MINUTES_PER_HOUR * MILLIS_PER_MINUTE; // Number of milliseconds in a day
216         threshold -= MILLIS_PER_MINUTE; // Remove one minute
217         if (timeInMillis > threshold) {
218             throw new InvalidParameterException("getMilliSeconds() is larger than 11:59 PM");
219         }
220     }
221 }