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 }