1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.core.impl.datetime;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.commons.lang.time.DurationFormatUtils;
20 import org.kuali.rice.core.api.datetime.DateTimeService;
21 import org.kuali.rice.core.api.CoreConstants;
22 import org.kuali.rice.core.api.config.property.ConfigContext;
23 import org.springframework.beans.factory.InitializingBean;
24
25 import java.sql.Time;
26 import java.sql.Timestamp;
27 import java.text.DateFormat;
28 import java.text.ParseException;
29 import java.text.ParsePosition;
30 import java.text.SimpleDateFormat;
31 import java.util.Arrays;
32 import java.util.Calendar;
33 import java.util.Collections;
34 import java.util.Date;
35 import java.util.List;
36
37
38
39
40
41
42 public class DateTimeServiceImpl implements DateTimeService, InitializingBean {
43
44
45
46 private static final String STRING_TO_DATE_FORMATS = "MM/dd/yyyy hh:mm a;MM/dd/yy;MM/dd/yyyy;MM-dd-yy;MM-dd-yyyy;MMddyy;MMMM dd;yyyy;MM/dd/yy HH:mm:ss;MM/dd/yyyy HH:mm:ss;MM-dd-yy HH:mm:ss;MMddyy HH:mm:ss;MMMM dd HH:mm:ss;yyyy HH:mm:ss";
47 private static final String STRING_TO_TIME_FORMATS = "hh:mm aa";
48 private static final String STRING_TO_TIMESTAMP_FORMATS = "MM/dd/yyyy hh:mm a;MM/dd/yy;MM/dd/yyyy;MM-dd-yy;MMddyy;MMMM dd;yyyy;MM/dd/yy HH:mm:ss;MM/dd/yyyy HH:mm:ss;MM-dd-yy HH:mm:ss;MMddyy HH:mm:ss;MMMM dd HH:mm:ss;yyyy HH:mm:ss";
49 private static final String DATE_TO_STRING_FORMAT_FOR_USER_INTERFACE = "MM/dd/yyyy";
50 private static final String TIME_TO_STRING_FORMAT_FOR_USER_INTERFACE = "hh:mm aa";
51 private static final String TIMESTAMP_TO_STRING_FORMAT_FOR_USER_INTERFACE = "MM/dd/yyyy hh:mm a";
52 private static final String DATE_TO_STRING_FORMAT_FOR_FILE_NAME = "yyyyMMdd";
53 private static final String TIMESTAMP_TO_STRING_FORMAT_FOR_FILE_NAME = "yyyyMMdd-HH-mm-ss-S";
54
55 protected String[] stringToDateFormats;
56 protected String[] stringToTimeFormats;
57 protected String[] stringToTimestampFormats;
58 protected String dateToStringFormatForUserInterface;
59 protected String timeToStringFormatForUserInterface;
60 protected String timestampToStringFormatForUserInterface;
61 protected String dateToStringFormatForFileName;
62 protected String timestampToStringFormatForFileName;
63
64
65
66
67
68 public String toDateString(Date date) {
69 return toString(date, dateToStringFormatForUserInterface);
70 }
71
72
73
74
75 public String toTimeString(Time time) {
76 return toString(time, timeToStringFormatForUserInterface);
77 }
78
79
80
81
82 public String toDateTimeString(Date date) {
83 return toString(date, timestampToStringFormatForUserInterface);
84 }
85
86
87
88
89
90 public String toString(Date date, String pattern) {
91 DateFormat dateFormat = new SimpleDateFormat(pattern);
92 dateFormat.setLenient(false);
93 return dateFormat.format(date);
94 }
95
96
97
98
99 public Date getCurrentDate() {
100 Calendar c = Calendar.getInstance();
101 c.setTime(new Date());
102 return c.getTime();
103 }
104
105
106
107
108 public Timestamp getCurrentTimestamp() {
109 return new java.sql.Timestamp(getCurrentDate().getTime());
110 }
111
112
113
114
115 public java.sql.Date getCurrentSqlDate() {
116 return new java.sql.Date(getCurrentDate().getTime());
117 }
118
119
120
121
122 public java.sql.Date getCurrentSqlDateMidnight() {
123
124 return java.sql.Date.valueOf(getCurrentSqlDate().toString());
125 }
126
127
128
129
130 public Calendar getCurrentCalendar() {
131 return getCalendar(getCurrentDate());
132 }
133
134
135
136
137 public Calendar getCalendar(Date date) {
138 if (date == null) {
139 throw new IllegalArgumentException("invalid (null) date");
140 }
141
142 Calendar currentCalendar = Calendar.getInstance();
143 currentCalendar.setTime(date);
144
145 return currentCalendar;
146 }
147
148
149
150
151
152
153 public Date convertToDate(String dateString) throws ParseException {
154 return parseAgainstFormatArray(dateString, stringToDateFormats);
155 }
156
157
158
159
160 public Date convertToDateTime(String dateTimeString) throws ParseException {
161 if (StringUtils.isBlank(dateTimeString)) {
162 throw new IllegalArgumentException("invalid (blank) date/time string");
163 }
164 return parseAgainstFormatArray(dateTimeString, stringToTimestampFormats);
165 }
166
167
168
169
170 public java.sql.Timestamp convertToSqlTimestamp(String timeString)
171 throws ParseException {
172 if (!StringUtils.isBlank(timeString)) {
173 return new java.sql.Timestamp(convertToDateTime(timeString).getTime());
174 }
175 return null;
176 }
177
178
179
180
181 public java.sql.Date convertToSqlDate(String dateString)
182 throws ParseException {
183 if (StringUtils.isBlank(dateString)) {
184 throw new IllegalArgumentException("invalid (blank) dateString");
185 }
186 Date date = parseAgainstFormatArray(dateString, stringToDateFormats);
187 return new java.sql.Date(date.getTime());
188 }
189
190
191
192
193 public java.sql.Time convertToSqlTime(String timeString)
194 throws ParseException {
195 if (StringUtils.isBlank(timeString)) {
196 throw new IllegalArgumentException("invalid (blank) dateString");
197 }
198 Date date = parseAgainstFormatArray(timeString, stringToTimeFormats);
199 return new java.sql.Time(date.getTime());
200 }
201
202 protected Date parseAgainstFormatArray(String dateString, String[] formats) throws ParseException {
203 dateString = dateString.trim();
204 StringBuffer exceptionMessage = new StringBuffer("Date or date/time string '")
205 .append(dateString)
206 .append("' could not be converted using any of the accepted formats: ");
207 for (String dateFormatString : formats) {
208 try {
209 return parse(dateString, dateFormatString);
210 } catch (ParseException e) {
211 exceptionMessage.append(dateFormatString).append(
212 " (error offset=").append(e.getErrorOffset()).append(
213 "),");
214 }
215 }
216 throw new ParseException(exceptionMessage.toString().substring(0,
217 exceptionMessage.length() - 1), 0);
218 }
219
220
221
222
223
224 public java.sql.Date convertToSqlDate(Timestamp timestamp)
225 throws ParseException {
226 return new java.sql.Date(timestamp.getTime());
227 }
228
229 public int dateDiff(Date startDate, Date endDate, boolean inclusive) {
230 Calendar startDateCalendar = Calendar.getInstance();
231 startDateCalendar.setTime(startDate);
232
233 Calendar endDateCalendar = Calendar.getInstance();
234 endDateCalendar.setTime(endDate);
235
236 int startDateOffset = -(startDateCalendar.get(Calendar.ZONE_OFFSET) + startDateCalendar
237 .get(Calendar.DST_OFFSET))
238 / (60 * 1000);
239
240 int endDateOffset = -(endDateCalendar.get(Calendar.ZONE_OFFSET) + endDateCalendar
241 .get(Calendar.DST_OFFSET))
242 / (60 * 1000);
243
244 if (startDateOffset > endDateOffset) {
245 startDateCalendar.add(Calendar.MINUTE, endDateOffset
246 - startDateOffset);
247 }
248
249 if (inclusive) {
250 startDateCalendar.add(Calendar.DATE, -1);
251 }
252
253 int dateDiff = Integer.parseInt(DurationFormatUtils.formatDuration(
254 endDateCalendar.getTimeInMillis()
255 - startDateCalendar.getTimeInMillis(), "d", true));
256
257 return dateDiff;
258 }
259
260 protected Date parse(String dateString, String pattern) throws ParseException {
261 if (!StringUtils.isBlank(dateString)) {
262 DateFormat dateFormat = new SimpleDateFormat(pattern);
263 dateFormat.setLenient(false);
264 ParsePosition parsePosition = new ParsePosition(0);
265 Date testDate = dateFormat.parse(dateString, parsePosition);
266
267
268 if (testDate == null) {
269 throw new ParseException("The date that you provided is invalid.",parsePosition.getErrorIndex());
270 } else if (parsePosition.getIndex() != dateString.length()) {
271 throw new ParseException("The date that you provided is invalid.",parsePosition.getIndex());
272 }
273
274
275 Calendar testCalendar = Calendar.getInstance();
276 testCalendar.setLenient(false);
277 testCalendar.setTime(testDate);
278 if (testCalendar.get(Calendar.YEAR) < 1000 || testCalendar.get(Calendar.YEAR) > 9999) {
279 throw new ParseException("The date that you provided is not between the years 1000 and 9999.",-1);
280 }
281
282 if(testCalendar.get(Calendar.YEAR) == 1970 && !pattern.contains("y".toLowerCase())){
283 Calendar curCalendar = Calendar.getInstance();
284 curCalendar.setTime(new java.util.Date());
285 testCalendar.set(Calendar.YEAR, curCalendar.get(Calendar.YEAR));
286 testDate = testCalendar.getTime();
287 }
288
289 return testDate;
290 }
291 return null;
292 }
293
294
295
296
297 public String toDateStringForFilename(Date date) {
298 SimpleDateFormat dateFormat = new SimpleDateFormat(dateToStringFormatForFileName);
299 return dateFormat.format(date);
300 }
301
302
303
304
305 public String toDateTimeStringForFilename(Date date) {
306 SimpleDateFormat dateFormat = new SimpleDateFormat(timestampToStringFormatForFileName);
307 return dateFormat.format(date);
308 }
309
310
311
312
313
314
315
316 @Override
317 public void afterPropertiesSet() throws Exception {
318 if (stringToDateFormats == null) {
319 stringToDateFormats = loadAndValidateFormats(CoreConstants.STRING_TO_DATE_FORMATS, STRING_TO_DATE_FORMATS);
320 }
321
322 if (stringToTimeFormats == null) {
323 stringToTimeFormats = loadAndValidateFormats(CoreConstants.STRING_TO_TIME_FORMATS, STRING_TO_TIME_FORMATS);
324 }
325
326 if (stringToTimestampFormats == null) {
327 stringToTimestampFormats = loadAndValidateFormats(CoreConstants.STRING_TO_TIMESTAMP_FORMATS, STRING_TO_TIMESTAMP_FORMATS);
328 }
329
330 if (dateToStringFormatForUserInterface == null) {
331 dateToStringFormatForUserInterface = loadAndValidateFormat(CoreConstants.DATE_TO_STRING_FORMAT_FOR_USER_INTERFACE, DATE_TO_STRING_FORMAT_FOR_USER_INTERFACE);
332 }
333
334 if (timeToStringFormatForUserInterface == null) {
335 timeToStringFormatForUserInterface = loadAndValidateFormat(CoreConstants.TIME_TO_STRING_FORMAT_FOR_USER_INTERFACE, TIME_TO_STRING_FORMAT_FOR_USER_INTERFACE);
336 }
337
338 if (timestampToStringFormatForUserInterface == null) {
339 timestampToStringFormatForUserInterface = loadAndValidateFormat(CoreConstants.TIMESTAMP_TO_STRING_FORMAT_FOR_USER_INTERFACE, TIMESTAMP_TO_STRING_FORMAT_FOR_USER_INTERFACE);
340 }
341
342 if (dateToStringFormatForFileName == null) {
343 dateToStringFormatForFileName = loadAndValidateFormat(CoreConstants.DATE_TO_STRING_FORMAT_FOR_FILE_NAME, DATE_TO_STRING_FORMAT_FOR_FILE_NAME);
344 }
345
346 if (timestampToStringFormatForFileName == null) {
347 timestampToStringFormatForFileName = loadAndValidateFormat(CoreConstants.TIMESTAMP_TO_STRING_FORMAT_FOR_FILE_NAME, TIMESTAMP_TO_STRING_FORMAT_FOR_FILE_NAME);
348 }
349 }
350
351
352
353
354
355
356
357
358
359 private List<String> parseConfigValues(String configValue) {
360 if (configValue == null || "".equals(configValue)) {
361 return Collections.emptyList();
362 }
363 return Arrays.asList(configValue.split(";"));
364 }
365
366
367
368
369
370
371
372 private List<String> loadFormats(String property, String deflt) {
373 return parseConfigValues(loadFormat(property, deflt));
374 }
375
376
377
378
379
380
381
382 private String[] loadAndValidateFormats(String property, String deflt) {
383 List<String> dateFormatParams = loadFormats(property, deflt);
384
385 String[] validFormats = new String[dateFormatParams.size()];
386
387 for (int i = 0; i < dateFormatParams.size(); i++) {
388 String dateFormatParam = dateFormatParams.get(i);
389 if (StringUtils.isBlank(dateFormatParam)) {
390 throw new IllegalArgumentException("Core/All/" + property + " parameter contains a blank semi-colon delimited substring");
391 }
392 else {
393
394 new SimpleDateFormat(dateFormatParam);
395 validFormats[i] = dateFormatParam;
396 }
397 }
398
399 return validFormats;
400 }
401
402
403
404
405
406
407
408 private String loadFormat(String property, String deflt) {
409 String format = ConfigContext.getCurrentContextConfig().getProperty(property);
410 if (StringUtils.isBlank(format)) {
411 format = deflt;
412 }
413 return format;
414 }
415
416
417
418
419
420
421
422
423 private String loadAndValidateFormat(String property, String deflt) {
424 String format = loadFormat(property, deflt);
425
426 new SimpleDateFormat(format);
427 return format;
428 }
429 }