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