This project has retired. For details please refer to its
Attic page.
001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.oozie.util;
019
020 import java.sql.Timestamp;
021 import java.text.DateFormat;
022 import java.text.ParseException;
023 import java.text.ParsePosition;
024 import java.text.SimpleDateFormat;
025 import java.util.Calendar;
026 import java.util.Date;
027 import java.util.GregorianCalendar;
028 import java.util.Locale;
029 import java.util.TimeZone;
030
031 import org.apache.oozie.coord.TimeUnit;
032
033 public class DateUtils {
034
035 private static final String[] W3CDATETIME_MASKS = {"yyyy-MM-dd'T'HH:mmz"};
036
037 /**
038 * Parses a Date out of a String with a date in W3C date-time format.
039 * <p/>
040 * It parsers the following formats:
041 * <ul>
042 * <li>"yyyy-MM-dd'T'HH:mm:ssz"</li>
043 * <li>"yyyy-MM-dd'T'HH:mmz"</li>
044 * <li>"yyyy-MM-dd"</li>
045 * <li>"yyyy-MM"</li>
046 * <li>"yyyy"</li>
047 * </ul>
048 * <p/>
049 * Refer to the java.text.SimpleDateFormat javadocs for details on the
050 * format of each element.
051 * <p/>
052 *
053 * @param sDate string to parse for a date.
054 * @return the Date represented by the given W3C date-time string. It
055 * returns <b>null</b> if it was not possible to parse the given
056 * string into a Date.
057 */
058 /*
059 * public static Date parseW3CDateTime(String sDate) { // if sDate has time
060 * on it, it injects 'GTM' before de TZ displacement to // allow the
061 * SimpleDateFormat parser to parse it properly int tIndex =
062 * sDate.indexOf("T"); if (tIndex > -1) { if (sDate.endsWith("Z")) { sDate =
063 * sDate.substring(0, sDate.length() - 1) + "+00:00"; } int tzdIndex =
064 * sDate.indexOf("+", tIndex); if (tzdIndex == -1) { tzdIndex =
065 * sDate.indexOf("-", tIndex); } if (tzdIndex > -1) { String pre =
066 * sDate.substring(0, tzdIndex); int secFraction = pre.indexOf(","); if
067 * (secFraction > -1) { pre = pre.substring(0, secFraction); } String post =
068 * sDate.substring(tzdIndex); sDate = pre + "GMT" + post; } } else { sDate
069 * += "T00:00GMT"; } return parseUsingMask(W3CDATETIME_MASKS, sDate); }
070 */
071 /**
072 * Parses a Date out of a string using an array of masks. <p/> It uses the masks in order until one of them succedes
073 * or all fail. <p/>
074 *
075 * @param masks array of masks to use for parsing the string
076 * @param sDate string to parse for a date.
077 * @return the Date represented by the given string using one of the given masks. It returns <b>null</b> if it was
078 * not possible to parse the the string with any of the masks.
079 */
080 private static Date parseUsingMask(String[] masks, String sDate) {
081 sDate = (sDate != null) ? sDate.trim() : null;
082 ParsePosition pp;
083 Date d = null;
084 if (sDate != null) {
085 for (int i = 0; d == null && i < masks.length; i++) {
086 DateFormat df = new SimpleDateFormat(masks[i], Locale.US);
087 df.setLenient(true);
088 pp = new ParsePosition(0);
089 d = df.parse(sDate, pp);
090 if (pp.getIndex() != sDate.length()) {
091 d = null;
092 }
093 }
094 }
095 return d;
096 }
097
098 private static final TimeZone UTC = getTimeZone("UTC");
099
100 private static DateFormat getISO8601DateFormat() {
101 DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
102 dateFormat.setTimeZone(UTC);
103 return dateFormat;
104 }
105
106 private static DateFormat getSpecificDateFormat(String format) {
107 DateFormat dateFormat = new SimpleDateFormat(format);
108 dateFormat.setTimeZone(UTC);
109 return dateFormat;
110 }
111
112 public static TimeZone getTimeZone(String tzId) {
113 if (tzId == null) {
114 throw new IllegalArgumentException("Invalid TimeZone: " + tzId);
115 }
116 TimeZone tz = TimeZone.getTimeZone(tzId);
117 if (!tz.getID().equals(tzId)) {
118 throw new IllegalArgumentException("Invalid TimeZone: " + tzId);
119 }
120 return tz;
121 }
122
123 public static Date parseDateUTC(String s) throws ParseException {
124 return getISO8601DateFormat().parse(s);
125 }
126
127 public static String formatDateUTC(Date d) throws Exception {
128 return (d != null) ? getISO8601DateFormat().format(d) : "NULL";
129 }
130
131 public static String formatDateCustom(Date d, String format) throws Exception {
132 return (d != null) ? getSpecificDateFormat(format).format(d) : "NULL";
133 }
134
135 public static String formatDateUTC(Calendar c) throws Exception {
136 return (c != null) ? formatDateUTC(c.getTime()) : "NULL";
137 }
138
139 /**
140 * This function returns number of hour in a day when given a Calendar with appropriate TZ. It consider DST to find
141 * the number of hours. Generally it is 24. At some tZ, in one day of a year it is 23 and another day it is 25
142 *
143 * @param cal: The date for which the number of hours is requested
144 * @return number of hour in that day.
145 */
146 public static int hoursInDay(Calendar cal) {
147 Calendar localCal = new GregorianCalendar(cal.getTimeZone());
148 localCal.set(Calendar.MILLISECOND, 0);
149 localCal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 30, 0);
150 localCal.add(Calendar.HOUR_OF_DAY, 24);
151 switch (localCal.get(Calendar.HOUR_OF_DAY)) {
152 case 1:
153 return 23;
154 case 23:
155 return 25;
156 default: // Case 0
157 return 24;
158 }
159 }
160
161 /**
162 * Determine whether a specific date is on DST change day
163 *
164 * @param cal: Date to know if it is DST change day. Appropriate TZ is specified
165 * @return true , if it DST change date otherwise false
166 */
167 public static boolean isDSTChangeDay(Calendar cal) {
168 return hoursInDay(cal) != 24;
169 }
170
171 /**
172 * Move the any date-time to the end of the duration. If endOfFlag == day, move the date to the end of day (24:00 on
173 * the same day or 00:00 on the next day) If endOf Flag = month. move the date to then end of current month
174 * Otherwise do nothing
175 *
176 * @param cal : Date-time needs to be moved to the end
177 * @param endOfFlag : day (for end of day) or month (for end of month) or empty
178 */
179 public static void moveToEnd(Calendar cal, TimeUnit endOfFlag) {
180 // TODO: Both logic needs to be checked
181 if (endOfFlag == TimeUnit.END_OF_DAY) { // 24:00:00
182 cal.add(Calendar.DAY_OF_MONTH, 1);
183 // cal.set(Calendar.HOUR_OF_DAY, cal
184 // .getActualMaximum(Calendar.HOUR_OF_DAY) + 1);// TODO:
185 cal.set(Calendar.HOUR_OF_DAY, 0);
186 cal.set(Calendar.MINUTE, 0);
187 cal.set(Calendar.SECOND, 0);
188 }
189 else {
190 if (endOfFlag == TimeUnit.END_OF_MONTH) {
191 cal.add(Calendar.MONTH, 1);
192 cal.set(Calendar.DAY_OF_MONTH, 1);
193 cal.set(Calendar.HOUR_OF_DAY, 0);
194 cal.set(Calendar.MINUTE, 0);
195 cal.set(Calendar.SECOND, 0);
196 }
197 }
198 }
199
200 /**
201 * Create a Calendar instance using the specified date and Time zone
202 * @param dateString
203 * @param tz : TimeZone
204 * @return appropriate Calendar object
205 * @throws Exception
206 */
207 public static Calendar getCalendar(String dateString, TimeZone tz) throws Exception {
208 Date date = DateUtils.parseDateUTC(dateString);
209 Calendar calDate = Calendar.getInstance();
210 calDate.setTime(date);
211 calDate.setTimeZone(tz);
212 return calDate;
213 }
214
215 /**
216 * Create a Calendar instance for UTC time zone using the specified date.
217 * @param dateString
218 * @return appropriate Calendar object
219 * @throws Exception
220 */
221 public static Calendar getCalendar(String dateString) throws Exception {
222 return getCalendar(dateString, DateUtils.getTimeZone("UTC"));
223 }
224
225 /**
226 * Convert java.sql.Timestamp to java.util.Date
227 *
228 * @param timestamp java.sql.Timestamp
229 * @return java.util.Date
230 */
231 public static java.util.Date toDate(java.sql.Timestamp timestamp) {
232 if (timestamp != null) {
233 long milliseconds = timestamp.getTime();
234 return new java.util.Date(milliseconds);
235 }
236 return null;
237 }
238
239 /**
240 * Convert java.util.Date to java.sql.Timestamp
241 *
242 * @param d java.util.Date
243 * @return java.sql.Timestamp
244 */
245 public static Timestamp convertDateToTimestamp(Date d) {
246 if (d != null) {
247 return new Timestamp(d.getTime());
248 }
249 return null;
250 }
251
252 /**
253 * Return the UTC date and time in W3C format down to second
254 * (yyyy-MM-ddTHH:mmZ). i.e.: 1997-07-16T19:20:30Z
255 *
256 * @return the formatted time string.
257 */
258 public static String convertDateToString(Date date) {
259 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
260 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
261 return sdf.format(date);
262 }
263
264 /**
265 * Return the UTC date and time in W3C format down to second
266 * (yyyy-MM-ddTHH:mmZ). i.e.: 1997-07-16T19:20Z The input date is a
267 * long (Unix Time Stamp)
268 *
269 * @return the formatted time string.
270 */
271 public static String convertDateToString(long timeStamp) {
272 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
273 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
274 return sdf.format(new Date(timeStamp));
275 }
276
277 }