001/**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.service;
017
018import org.junit.Test;
019import org.kuali.rice.core.api.CoreApiServiceLocator;
020import org.kuali.rice.krad.test.KRADTestCase;
021
022import java.text.ParseException;
023import java.text.SimpleDateFormat;
024import java.util.Calendar;
025import java.util.Date;
026
027import static org.junit.Assert.*;
028
029/**
030 * DateTimeServiceTest tests {@link org.kuali.rice.core.api.datetime.DateTimeService}
031 */
032public class DateTimeServiceTest extends KRADTestCase {
033
034    /**
035     * tests that DateTimeService returns a correct current date
036     *
037     * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentDate()
038     */
039    @Test public void testGetCurrentDate() {
040        Date beforeServiceDate = new Date();
041        Date serviceDate = CoreApiServiceLocator.getDateTimeService().getCurrentDate();
042        Date afterServiceDate = new Date();
043
044        assertTrue("beforeServiceDate not <= serviceDate", beforeServiceDate.before(serviceDate) || beforeServiceDate.equals(serviceDate));
045        assertTrue("afterServiceDate not >= serviceDate", afterServiceDate.after(serviceDate) || afterServiceDate.equals(serviceDate));
046    }
047
048    /**
049     * tests that DateTimeService returns a correct current SQL date
050     *
051     * @see org.kuali.rice.core.api.datetime.DateTimeService#getCurrentSqlDate()
052     */
053    @Test public void testGetCurrentSqlDate() {
054        java.sql.Date serviceDate = CoreApiServiceLocator.getDateTimeService().getCurrentSqlDate();
055
056        java.sql.Date beforeServiceDate = new java.sql.Date(serviceDate.getTime() - 100);
057        java.sql.Date afterServiceDate = new java.sql.Date(serviceDate.getTime() + 100);
058
059        assertTrue("beforeServiceDate not <= serviceDate", beforeServiceDate.before(serviceDate) || beforeServiceDate.equals(serviceDate));
060        assertTrue("afterServiceDate not >= serviceDate", afterServiceDate.after(serviceDate) || afterServiceDate.equals(serviceDate));
061    }
062
063    /**
064     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#getCurrentSqlDateMidnight()}
065     * @throws InterruptedException
066     */
067    @SuppressWarnings("deprecation")
068    @Test public void testGetCurrentSqlDateMidnight() throws InterruptedException {
069        // this test is invalid within 1 second of midnight, so wait for it
070        waitForMidnightIfWithinOneSecond();
071        java.sql.Date before = CoreApiServiceLocator.getDateTimeService().getCurrentSqlDateMidnight();
072        java.util.Date checkBefore = new java.util.Date();
073        Thread.sleep(500); // makes sure the clock has time to tick
074        java.util.Date checkAfter = new java.util.Date();
075        java.sql.Date after = CoreApiServiceLocator.getDateTimeService().getCurrentSqlDateMidnight();
076        assertTrue(checkBefore.before(checkAfter)); // make sure the clock did tick
077        assertEquals(before.getTime(), after.getTime());
078        java.util.Date afterUtil = new java.util.Date(after.getTime());
079        // these methods in java.sql.Date are not just deprecated; they throw IllegalArgumentException.
080        assertEquals(0, afterUtil.getHours());
081        assertEquals(0, afterUtil.getMinutes());
082        assertEquals(0, afterUtil.getSeconds());
083    }
084
085    /**
086     * {@link #testGetCurrentSqlDateMidnight()} is invalid within 1 second of midnight, so wait for it
087     *
088     * @throws InterruptedException
089     */
090    @SuppressWarnings("deprecation")
091    private static void waitForMidnightIfWithinOneSecond() throws InterruptedException {
092        java.util.Date now = new java.util.Date();
093        java.util.Date then = new java.util.Date(now.getTime() + 1000);
094        if (now.getDay() != then.getDay()) {
095            Thread.sleep(1000);
096        }
097    }
098
099    /**
100     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#getCurrentCalendar()}
101     */
102    @Test public void testGetCurrentCalendar() {
103        Date beforeServiceDate = new Date();
104        Calendar serviceCalendar = CoreApiServiceLocator.getDateTimeService().getCurrentCalendar();
105        Date afterServiceDate = new Date();
106
107        // extract the calendar's Date, for easier testing
108        Date serviceDate = serviceCalendar.getTime();
109
110        assertTrue("beforeServiceDate not <= serviceDate", beforeServiceDate.before(serviceDate) || beforeServiceDate.equals(serviceDate));
111        assertTrue("afterServiceDate not >= serviceDate", afterServiceDate.after(serviceDate) || afterServiceDate.equals(serviceDate));
112    }
113
114    /**
115     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTimestamp(String)} with a null value
116     *
117     * @throws ParseException
118     */
119    @Test public void testConvertToSqlTimestamp_blankTimeString() throws ParseException {
120        assertNull(CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(null));
121    }
122
123    /**
124     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTimestamp(String)} with an invalid time value
125     */
126    @Test public void testConvertToSqlTimestamp_invalidTimeString() {
127        boolean failedAsExpected = false;
128        try {
129            CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp("foo");
130        }
131        catch (ParseException e) {
132            failedAsExpected = true;
133        }
134        assertTrue("invalid timeString failed to fail", failedAsExpected);
135    }
136
137    /**
138     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTimestamp(String)} with a valid time string
139     *
140     * @throws ParseException
141     */
142    @Test public void testConvertToSqlTimestamp_validTimeString() throws ParseException {
143        java.sql.Timestamp serviceTimestamp = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp("05/01/1966 02:41 PM");
144        Calendar serviceCalendar = Calendar.getInstance();
145        serviceCalendar.setTime(serviceTimestamp);
146        assertEquals("unexpected year", 1966, serviceCalendar.get(Calendar.YEAR));
147        assertEquals("unexpected month", 5, serviceCalendar.get(Calendar.MONTH) + 1);
148        assertEquals("unexpected day", 1, serviceCalendar.get(Calendar.DAY_OF_MONTH));
149        assertEquals("unexpected hours", 14, serviceCalendar.get(Calendar.HOUR_OF_DAY));
150        assertEquals("unexpected minutes", 41, serviceCalendar.get(Calendar.MINUTE));
151        assertEquals("unexpected seconds", 0, serviceCalendar.get(Calendar.SECOND));
152        assertEquals("unexpected milliseconds", serviceTimestamp.getNanos(), 0);
153    }
154
155    /**
156     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlDate(String)} with a blank value
157     *
158     * @throws ParseException
159     */
160    @Test public void testConvertToSqlDate_blankDateString() throws ParseException {
161        boolean failedAsExpected = false;
162
163        try {
164            CoreApiServiceLocator.getDateTimeService().convertToSqlDate("");
165        }
166        catch (IllegalArgumentException e) {
167            failedAsExpected = true;
168        }
169
170        assertTrue("blank dateString failed to fail", failedAsExpected);
171    }
172
173    /**
174     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlDate(String)} with an invalid date string
175     */
176    @Test public void testConvertToSqlDate_invalidDateString() {
177        boolean failedAsExpected = false;
178
179        try {
180            CoreApiServiceLocator.getDateTimeService().convertToSqlDate("foo");
181        }
182        catch (ParseException e) {
183            failedAsExpected = true;
184        }
185
186        assertTrue("invalid dateString failed to fail", failedAsExpected);
187    }
188
189    /**
190     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlDate(String)} with a valid date string
191     */
192    @Test public void testConvertToSqlDate_validDateString() throws ParseException {
193        java.sql.Date serviceDate = CoreApiServiceLocator.getDateTimeService().convertToSqlDate("05/01/1966");
194
195        Calendar serviceCalendar = Calendar.getInstance();
196        serviceCalendar.setTime(serviceDate);
197
198        assertEquals("unexpected year", 1966, serviceCalendar.get(Calendar.YEAR));
199        assertEquals("unexpected month", 5, serviceCalendar.get(Calendar.MONTH) + 1);
200        assertEquals("unexpected day", 1, serviceCalendar.get(Calendar.DAY_OF_MONTH));
201        assertEquals("unexpected hours", 0, serviceCalendar.get(Calendar.HOUR_OF_DAY));
202        assertEquals("unexpected minutes", 0, serviceCalendar.get(Calendar.MINUTE));
203        assertEquals("unexpected seconds", 0, serviceCalendar.get(Calendar.SECOND));
204    }
205
206    /**
207     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTime(String)} with a blank value
208     *
209     * @throws ParseException
210     */
211    @Test public void testConvertToSqlTime_blankTimeString() throws ParseException {
212        boolean failedAsExpected = false;
213
214        try {
215            CoreApiServiceLocator.getDateTimeService().convertToSqlTime("");
216        }
217        catch (IllegalArgumentException e) {
218            failedAsExpected = true;
219        }
220
221        assertTrue("blank timeString failed to fail", failedAsExpected);
222    }
223
224    /**
225     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTime(String)} with an invalid time string
226     */
227    @Test public void testConvertToSqlTime_invalidTimeString() {
228        boolean failedAsExpected = false;
229
230        try {
231            CoreApiServiceLocator.getDateTimeService().convertToSqlTime("foo");
232        }
233        catch (ParseException e) {
234            failedAsExpected = true;
235        }
236
237        assertTrue("invalid timeString failed to fail", failedAsExpected);
238    }
239
240    /**
241     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#convertToSqlTime(String)} with a valid date string
242     */
243    @Test public void testConvertToSqlTime_validTimeString() throws ParseException {
244        java.sql.Time serviceTime = CoreApiServiceLocator.getDateTimeService().convertToSqlTime("10:28 am");
245
246        Calendar serviceCalendar = Calendar.getInstance();
247        serviceCalendar.setTime(serviceTime);
248
249        assertEquals("unexpected hours", 10, serviceCalendar.get(Calendar.HOUR_OF_DAY));
250        assertEquals("unexpected minutes", 28, serviceCalendar.get(Calendar.MINUTE));
251        assertEquals("unexpected seconds", 0, serviceCalendar.get(Calendar.SECOND));
252    }
253
254    /**
255     * tests {@link org.kuali.rice.core.api.datetime.DateTimeService#dateDiff(java.util.Date, java.util.Date, boolean)}
256     *
257     * @throws ParseException
258     */
259    @Test public void testDateDiff() throws ParseException {
260        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
261
262        // regular 1 year period
263        Date date1 = sdf.parse("01/01/2006");
264        Date date2 = sdf.parse("12/31/2006");
265
266        assertEquals("365", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
267        assertEquals("364", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
268
269        // one year period w/ leap year
270        date1 = sdf.parse("01/01/2008");
271        date2 = sdf.parse("12/31/2008");
272
273        assertEquals("366", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
274        assertEquals("365", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
275
276        assertEquals("366", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
277        assertEquals("365", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
278
279        // one year period w/ leap year, beginning in the middle of the year
280        date1 = sdf.parse("07/01/2007");
281        date2 = sdf.parse("06/30/2008");
282
283        assertEquals("366", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
284        assertEquals("365", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
285
286        // one year period, start and end in middle of the year
287        date1 = sdf.parse("07/01/2006");
288        date2 = sdf.parse("06/30/2007");
289
290        assertEquals("365", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
291        assertEquals("364", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
292
293        // one month period
294        date1 = sdf.parse("01/01/2006");
295        date2 = sdf.parse("01/31/2006");
296
297        assertEquals("31", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
298        assertEquals("30", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
299
300        // another one month period
301        date1 = sdf.parse("04/14/2006");
302        date2 = sdf.parse("05/13/2006");
303
304        assertEquals("30", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
305        assertEquals("29", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
306
307        // one day period
308        date1 = sdf.parse("01/01/2006");
309        date2 = sdf.parse("01/02/2006");
310
311        assertEquals("2", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
312        assertEquals("1", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
313
314        // arbitrary dates
315        date1 = sdf.parse("01/01/2006");
316        date2 = sdf.parse("06/30/2006");
317
318        assertEquals("181", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
319
320        date1 = sdf.parse("07/01/2006");
321        date2 = sdf.parse("12/31/2006");
322
323        assertEquals("184", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, true)));
324
325        // within same month
326        date1 = sdf.parse("07/01/2006");
327        date2 = sdf.parse("07/20/2006");
328
329        assertEquals("19", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
330
331        // same day
332        date1 = sdf.parse("07/20/2006");
333        date2 = sdf.parse("07/20/2006");
334
335        assertEquals("0", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
336
337        // end date is prior to start date
338        date1 = sdf.parse("07/25/2006");
339        date2 = sdf.parse("07/20/2006");
340
341        assertEquals("-5", Integer.toString(CoreApiServiceLocator.getDateTimeService().dateDiff(date1, date2, false)));
342    }
343}