Coverage Report - org.kuali.rice.core.impl.datetime.DateTimeServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
DateTimeServiceImpl
0%
0/108
0%
0/52
2.905
 
 1  
 /**
 2  
  * Copyright 2005-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 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.Timestamp;
 26  
 import java.text.DateFormat;
 27  
 import java.text.ParseException;
 28  
 import java.text.ParsePosition;
 29  
 import java.text.SimpleDateFormat;
 30  
 import java.util.Arrays;
 31  
 import java.util.Calendar;
 32  
 import java.util.Collections;
 33  
 import java.util.Date;
 34  
 import java.util.List;
 35  
 
 36  
 /**
 37  
  * This class is the service implementation for a DateTime structure. This is
 38  
  * the default, Kuali delivered implementation.
 39  
  */
 40  
 //@Transactional
 41  0
 public class DateTimeServiceImpl implements DateTimeService, InitializingBean {
 42  
         protected String[] stringToDateFormats;
 43  
         protected String[] stringToTimestampFormats;
 44  
         protected String dateToStringFormatForUserInterface;
 45  
         protected String timestampToStringFormatForUserInterface;
 46  
         protected String dateToStringFormatForFileName;
 47  
         protected String timestampToStringFormatForFileName;
 48  
 
 49  
                 
 50  
         /**
 51  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#toDateString(java.util.Date)
 52  
          */
 53  
         public String toDateString(Date date) {
 54  0
                 return toString(date, dateToStringFormatForUserInterface);
 55  
         }
 56  
 
 57  
         /**
 58  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#toDateTimeString(java.util.Date)
 59  
          */
 60  
         public String toDateTimeString(Date date) {
 61  0
                 return toString(date, timestampToStringFormatForUserInterface);
 62  
         }
 63  
 
 64  
         /**
 65  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#toString(java.util.Date,
 66  
          *      java.lang.String)
 67  
          */
 68  
         public String toString(Date date, String pattern) {
 69  0
                 DateFormat dateFormat = new SimpleDateFormat(pattern);
 70  0
                 dateFormat.setLenient(false);
 71  0
                 return dateFormat.format(date);
 72  
         }
 73  
 
 74  
         /**
 75  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentDate()
 76  
          */
 77  
         public Date getCurrentDate() {
 78  0
                 Calendar c = Calendar.getInstance();
 79  0
                 c.setTime(new Date());
 80  0
                 return c.getTime();
 81  
         }
 82  
 
 83  
         /**
 84  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentTimestamp()
 85  
          */
 86  
         public Timestamp getCurrentTimestamp() {
 87  0
                 return new java.sql.Timestamp(getCurrentDate().getTime());
 88  
         }
 89  
 
 90  
         /**
 91  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentSqlDate()
 92  
          */
 93  
         public java.sql.Date getCurrentSqlDate() {
 94  0
                 return new java.sql.Date(getCurrentDate().getTime());
 95  
         }
 96  
 
 97  
         /**
 98  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentSqlDateMidnight()
 99  
          */
 100  
         public java.sql.Date getCurrentSqlDateMidnight() {
 101  
                 // simple and not unduely inefficient way to truncate the time component
 102  0
                 return java.sql.Date.valueOf(getCurrentSqlDate().toString());
 103  
         }
 104  
 
 105  
         /**
 106  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentCalendar()
 107  
          */
 108  
         public Calendar getCurrentCalendar() {
 109  0
                 return getCalendar(getCurrentDate());
 110  
         }
 111  
 
 112  
         /**
 113  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#getCalendar
 114  
          */
 115  
         public Calendar getCalendar(Date date) {
 116  0
                 if (date == null) {
 117  0
                         throw new IllegalArgumentException("invalid (null) date");
 118  
                 }
 119  
 
 120  0
                 Calendar currentCalendar = Calendar.getInstance();
 121  0
                 currentCalendar.setTime(date);
 122  
 
 123  0
                 return currentCalendar;
 124  
         }
 125  
 
 126  
         /**
 127  
          * Formats strings into dates using the format string in the KR-NS/All/STRING_TO_DATE_FORMATS parameter
 128  
          *
 129  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#convertToDate(java.lang.String)
 130  
          */
 131  
         public Date convertToDate(String dateString) throws ParseException {
 132  0
                 return parseAgainstFormatArray(dateString, stringToDateFormats);
 133  
         }
 134  
 
 135  
         /**
 136  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#convertToDateTime(java.lang.String)
 137  
          */
 138  
         public Date convertToDateTime(String dateTimeString) throws ParseException {
 139  0
                 if (StringUtils.isBlank(dateTimeString)) {
 140  0
                         throw new IllegalArgumentException("invalid (blank) date/time string");
 141  
                 }
 142  0
                 return parseAgainstFormatArray(dateTimeString, stringToTimestampFormats);
 143  
         }
 144  
 
 145  
         /**
 146  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTimestamp(java.lang.String)
 147  
          */
 148  
         public java.sql.Timestamp convertToSqlTimestamp(String timeString)
 149  
                         throws ParseException {
 150  0
                 if (!StringUtils.isBlank(timeString)) {
 151  0
                         return new java.sql.Timestamp(convertToDateTime(timeString).getTime());
 152  
                 }
 153  0
         return null;
 154  
         }
 155  
 
 156  
         /**
 157  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlDate(java.lang.String)
 158  
          */
 159  
         public java.sql.Date convertToSqlDate(String dateString)
 160  
                         throws ParseException {
 161  0
                 if (StringUtils.isBlank(dateString)) {
 162  0
                         throw new IllegalArgumentException("invalid (blank) timeString");
 163  
                 }
 164  0
                 Date date = parseAgainstFormatArray(dateString, stringToDateFormats);
 165  0
                 return new java.sql.Date(date.getTime());
 166  
         }
 167  
 
 168  
         protected Date parseAgainstFormatArray(String dateString, String[] formats) throws ParseException {
 169  0
                 dateString = dateString.trim();
 170  0
                 StringBuffer exceptionMessage = new StringBuffer("Date or date/time string '")
 171  
                                 .append(dateString)
 172  
                                 .append("' could not be converted using any of the accepted formats: ");
 173  0
                 for (String dateFormatString : formats) {
 174  
                         try {
 175  0
                                 return parse(dateString, dateFormatString);
 176  0
                         } catch (ParseException e) {
 177  0
                                 exceptionMessage.append(dateFormatString).append(
 178  
                                                 " (error offset=").append(e.getErrorOffset()).append(
 179  
                                                 "),");
 180  
                         }
 181  
                 }
 182  0
                 throw new ParseException(exceptionMessage.toString().substring(0,
 183  
                                 exceptionMessage.length() - 1), 0);
 184  
         }
 185  
 
 186  
         /**
 187  
          * @throws ParseException
 188  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlDate(java.sql.Timestamp)
 189  
          */
 190  
         public java.sql.Date convertToSqlDate(Timestamp timestamp)
 191  
                         throws ParseException {
 192  0
                 return new java.sql.Date(timestamp.getTime());
 193  
         }
 194  
 
 195  
         public int dateDiff(Date startDate, Date endDate, boolean inclusive) {
 196  0
                 Calendar startDateCalendar = Calendar.getInstance();
 197  0
                 startDateCalendar.setTime(startDate);
 198  
 
 199  0
                 Calendar endDateCalendar = Calendar.getInstance();
 200  0
                 endDateCalendar.setTime(endDate);
 201  
 
 202  0
                 int startDateOffset = -(startDateCalendar.get(Calendar.ZONE_OFFSET) + startDateCalendar
 203  
                                 .get(Calendar.DST_OFFSET))
 204  
                                 / (60 * 1000);
 205  
 
 206  0
                 int endDateOffset = -(endDateCalendar.get(Calendar.ZONE_OFFSET) + endDateCalendar
 207  
                                 .get(Calendar.DST_OFFSET))
 208  
                                 / (60 * 1000);
 209  
 
 210  0
                 if (startDateOffset > endDateOffset) {
 211  0
                         startDateCalendar.add(Calendar.MINUTE, endDateOffset
 212  
                                         - startDateOffset);
 213  
                 }
 214  
 
 215  0
                 if (inclusive) {
 216  0
                         startDateCalendar.add(Calendar.DATE, -1);
 217  
                 }
 218  
 
 219  0
                 int dateDiff = Integer.parseInt(DurationFormatUtils.formatDuration(
 220  
                                 endDateCalendar.getTimeInMillis()
 221  
                                                 - startDateCalendar.getTimeInMillis(), "d", true));
 222  
 
 223  0
                 return dateDiff;
 224  
         }
 225  
 
 226  
         protected Date parse(String dateString, String pattern) throws ParseException {
 227  0
                 if (!StringUtils.isBlank(dateString)) {
 228  0
                         DateFormat dateFormat = new SimpleDateFormat(pattern);
 229  0
                         dateFormat.setLenient(false);
 230  0
                         ParsePosition parsePosition = new ParsePosition(0);
 231  0
                         Date testDate = dateFormat.parse(dateString, parsePosition);
 232  
                         
 233  
                         // Ensure that the entire date String can be parsed by the current format.
 234  0
                         if (testDate == null) {
 235  0
                                 throw new ParseException("The date that you provided is invalid.",parsePosition.getErrorIndex());
 236  0
                         } else if (parsePosition.getIndex() != dateString.length()) {
 237  0
                                 throw new ParseException("The date that you provided is invalid.",parsePosition.getIndex());
 238  
                         }
 239  
 
 240  
                         // Ensure that the date's year lies between 1000 and 9999, to help prevent database-related date errors.
 241  0
                         Calendar testCalendar = Calendar.getInstance();
 242  0
                         testCalendar.setLenient(false);
 243  0
                         testCalendar.setTime(testDate);
 244  0
                         if (testCalendar.get(Calendar.YEAR) < 1000 || testCalendar.get(Calendar.YEAR) > 9999) {
 245  0
                                 throw new ParseException("The date that you provided is not between the years 1000 and 9999.",-1);
 246  
                         }
 247  
                         
 248  0
                         if(testCalendar.get(Calendar.YEAR) == 1970 && !pattern.contains("y".toLowerCase())){                            
 249  0
                             Calendar curCalendar = Calendar.getInstance();
 250  0
                             curCalendar.setTime(new java.util.Date());
 251  0
                             testCalendar.set(Calendar.YEAR, curCalendar.get(Calendar.YEAR));
 252  0
                                 testDate = testCalendar.getTime();
 253  
                         }
 254  
                         
 255  0
                         return testDate;
 256  
                 }
 257  0
                 return null;
 258  
         }
 259  
 
 260  
         /**
 261  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#toDateStringForFilename(java.util.Date)
 262  
          */
 263  
         public String toDateStringForFilename(Date date) {
 264  0
                 SimpleDateFormat dateFormat = new SimpleDateFormat(dateToStringFormatForFileName);
 265  0
                 return dateFormat.format(date);
 266  
         }
 267  
 
 268  
         /**
 269  
          * @see org.kuali.rice.core.api.datetime.DateTimeService#toDateTimeStringForFilename(java.util.Date)
 270  
          */
 271  
         public String toDateTimeStringForFilename(Date date) {
 272  0
                 SimpleDateFormat dateFormat = new SimpleDateFormat(timestampToStringFormatForFileName);
 273  0
                 return dateFormat.format(date);
 274  
         }
 275  
         
 276  
         /**
 277  
          * 
 278  
          * The dateTime config vars are ';' seperated. This method should probably 
 279  
          * be on the config interface.
 280  
          * 
 281  
          * @param configValue
 282  
          * @return
 283  
          */
 284  
         private List<String> parseConfigValues(String configValue) {
 285  0
             if (configValue == null || "".equals(configValue)) {
 286  0
                 return Collections.emptyList();
 287  
             }
 288  0
             return Arrays.asList(configValue.split(";"));
 289  
         }
 290  
         /**
 291  
          * This overridden method ...
 292  
          * 
 293  
          * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 294  
          */
 295  
         @Override
 296  
         public void afterPropertiesSet() throws Exception {
 297  0
                 if (stringToDateFormats == null) {
 298  0
                         List<String> dateFormatParams = parseConfigValues(ConfigContext.getCurrentContextConfig().getProperty(CoreConstants.STRING_TO_DATE_FORMATS));
 299  
 
 300  0
                         stringToDateFormats = new String[dateFormatParams.size()];
 301  
 
 302  0
                         for (int i = 0; i < dateFormatParams.size(); i++) {
 303  0
                                 String dateFormatParam = dateFormatParams.get(i);
 304  0
                                 if (StringUtils.isBlank(dateFormatParam)) {
 305  0
                                         throw new IllegalArgumentException("Core/All/STRING_TO_DATE_FORMATS parameter contains a blank semi-colon delimited substring");
 306  
                                 }
 307  
                                 else {
 308  
                                         // try to create a new SimpleDateFormat to try to detect illegal patterns
 309  0
                                         new SimpleDateFormat(dateFormatParam);
 310  0
                                         stringToDateFormats[i] = dateFormatParam;
 311  
                                 }
 312  
                         }
 313  
                 }
 314  
 
 315  0
                 if (stringToTimestampFormats == null) {
 316  0
                         List<String> dateFormatParams = parseConfigValues(ConfigContext.getCurrentContextConfig().getProperty(CoreConstants.STRING_TO_TIMESTAMP_FORMATS));                        
 317  
 
 318  0
                         stringToTimestampFormats = new String[dateFormatParams.size()];
 319  
 
 320  0
                         for (int i = 0; i < dateFormatParams.size(); i++) {
 321  0
                                 String dateFormatParam = dateFormatParams.get(i);
 322  0
                                 if (StringUtils.isBlank(dateFormatParam)) {
 323  0
                                         throw new IllegalArgumentException("Core/All/STRING_TO_TIMESTAMP_FORMATS parameter contains a blank semi-colon delimited substring");
 324  
                                 }
 325  
                                 else {
 326  
                                         // try to create a new SimpleDateFormat to try to detect illegal patterns
 327  0
                                         new SimpleDateFormat(dateFormatParam);
 328  0
                                         stringToTimestampFormats[i] = dateFormatParam;
 329  
                                 }
 330  
                         }
 331  
                 }
 332  
 
 333  0
                 if (dateToStringFormatForUserInterface == null) {
 334  0
                         dateToStringFormatForUserInterface = ConfigContext.getCurrentContextConfig().getProperty(CoreConstants.DATE_TO_STRING_FORMAT_FOR_USER_INTERFACE);
 335  
                         // construct new SDF to make sure it's properly formatted
 336  0
                         new SimpleDateFormat(dateToStringFormatForUserInterface);
 337  
                 }
 338  
 
 339  0
                 if (timestampToStringFormatForUserInterface == null) {
 340  0
                         timestampToStringFormatForUserInterface = ConfigContext.getCurrentContextConfig().getProperty(CoreConstants.TIMESTAMP_TO_STRING_FORMAT_FOR_USER_INTERFACE);                        
 341  
                         // construct new SDF to make sure it's properly formatted
 342  0
                         new SimpleDateFormat(timestampToStringFormatForUserInterface);
 343  
                 }
 344  
 
 345  0
                 if (dateToStringFormatForFileName == null) {
 346  0
                         dateToStringFormatForFileName = ConfigContext.getCurrentContextConfig().getProperty(CoreConstants.DATE_TO_STRING_FORMAT_FOR_FILE_NAME);
 347  
                         
 348  
                         // construct new SDF to make sure it's properly formatted
 349  0
                         new SimpleDateFormat(dateToStringFormatForFileName);
 350  
                 }
 351  
 
 352  0
                 if (timestampToStringFormatForFileName == null) {
 353  0
                         timestampToStringFormatForFileName = ConfigContext.getCurrentContextConfig().getProperty(CoreConstants.TIMESTAMP_TO_STRING_FORMAT_FOR_FILE_NAME);
 354  
                         
 355  
                         // construct new SDF to make sure it's properly formatted
 356  0
                         new SimpleDateFormat(timestampToStringFormatForFileName);
 357  
                 }                
 358  0
         }
 359  
 }