/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.server.types.mcompat.mtypes; import com.foundationdb.server.error.InvalidDateFormatException; import com.foundationdb.server.types.mcompat.mtypes.MDateAndTime.StringType; import org.joda.time.DateTimeZone; import org.junit.Test; import java.util.Arrays; import static com.foundationdb.server.types.mcompat.mtypes.MDateAndTime.*; import static com.foundationdb.server.types.mcompat.mtypes.MDateAndTime.StringType.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class MDateAndTimeTest { @Test public void testAdjustTwoDigitYear() { assertEquals(2000, adjustTwoDigitYear(0)); assertEquals(2013, adjustTwoDigitYear(13)); assertEquals(2069, adjustTwoDigitYear(69)); assertEquals(1970, adjustTwoDigitYear(70)); assertEquals(1999, adjustTwoDigitYear(99)); assertEquals(100, adjustTwoDigitYear(100)); } @Test public void testParseDateOrTime() { // TIME doParseDateOrTime(TIME_ST, "1 1:1:0", 0, 0, 0, 25, 1, 0); doParseDateOrTime(TIME_ST, "-12:0:2", 0, 0, 0, -12, 0, 2); doParseDateOrTime(TIME_ST, "-1 3:4:5", 0, 0, 0, -27, 4, 5); doParseDateOrTime(TIME_ST, "12:30:10", 0, 0, 0, 12, 30, 10); doParseDateOrTime(TIME_ST, "25:30:10", 0, 0, 0, 25, 30, 10); doParseDateOrTime(TIME_ST, "25:30:10-0400", 0, 0, 0, 25, 30, 10); doParseDateOrTime(TIME_ST, "25:30:10-04:00", 0, 0, 0, 25, 30, 10); doParseDateOrTime(TIME_ST, "25:30:10-040000", 0, 0, 0, 25, 30, 10); doParseDateOrTime(TIME_ST, "25:30:10-04:00:00", 0, 0, 0, 25, 30, 10); // DATE doParseDateOrTime(DATE_ST, "2002-12-30", 2002, 12, 30, 0, 0, 0); doParseDateOrTime(DATE_ST, "2002/12/30", 2002, 12, 30, 0, 0, 0); doParseDateOrTime(DATE_ST, "02-12-30", 2002, 12, 30, 0, 0, 0); doParseDateOrTime(DATE_ST, "02/12/30", 2002, 12, 30, 0, 0, 0); doParseDateOrTime(DATE_ST, "95-12-30", 1995, 12, 30, 0, 0, 0); doParseDateOrTime(DATE_ST, "95/12/30", 1995, 12, 30, 0, 0, 0); doParseDateOrTime(DATE_ST, "2014-08-27-0400", 2014, 8, 27, 0, 0, 0); doParseDateOrTime(DATE_ST, "2014-08-27-04:00", 2014, 8, 27, 0, 0, 0); doParseDateOrTime(DATE_ST, "2014-08-27-040000", 2014, 8, 27, 0, 0, 0); doParseDateOrTime(DATE_ST, "2014-08-27-04:00:00", 2014, 8, 27, 0, 0, 0); // DATE with zeros doParseDateOrTime(DATE_ST, "0000-00-00", 0, 0, 0, 0, 0, 0); doParseDateOrTime(DATE_ST, "0000-00-01", 0, 0, 1, 0, 0, 0); doParseDateOrTime(DATE_ST, "0000-01-00", 0, 1, 0, 0, 0, 0); doParseDateOrTime(DATE_ST, "0000-01-01", 0, 1, 1, 0, 0, 0); doParseDateOrTime(DATE_ST, "0001-00-00", 1, 0, 0, 0, 0, 0); doParseDateOrTime(DATE_ST, "0001-00-01", 1, 0, 1, 0, 0, 0); doParseDateOrTime(DATE_ST, "0001-01-00", 1, 1, 0, 0, 0, 0); doParseDateOrTime(DATE_ST, "0001-01-01", 1, 1, 1, 0, 0, 0); // DATETIME doParseDateOrTime(DATETIME_ST, "1900-1-2 12:30:10", 1900, 1, 2, 12, 30, 10); doParseDateOrTime(DATETIME_ST, "2012-04-09T12:45:00", 2012, 4, 9, 12, 45, 0); doParseDateOrTime(DATETIME_ST, "2013-04-03T14:55:08.249Z-05:00", 2013, 4, 3, 14, 55, 8); doParseDateOrTime(DATETIME_ST, "2013/04/03 14.55.08", 2013, 4, 3, 14, 55, 8); doParseDateOrTime(DATETIME_ST, "2014-05-21 16:00:35.091000-0400", 2014, 5, 21, 16, 0, 35); doParseDateOrTime(DATETIME_ST, "2014-05-21 16:00:35.091000-04:00", 2014, 5, 21, 16, 0, 35); doParseDateOrTime(DATETIME_ST, "2014-05-21 16:00:35.091000-040000", 2014, 5, 21, 16, 0, 35); doParseDateOrTime(DATETIME_ST, "2014-05-21 16:00:35.091000-04:00:00", 2014, 5, 21, 16, 0, 35); // INVALID doParseDateOrTime(INVALID_TIME_ST, "", 0, 0, 0, 0, 0, 0); doParseDateOrTime(INVALID_DATE_ST, "01-01-02am", 2001, 1, 0, 0, 0, 0); doParseDateOrTime(INVALID_DATETIME_ST, "1900-1-2 25:30:10", 1900, 1, 2, 25, 30, 10); // UNPARSABLE doParseDateOrTime(UNPARSABLE, "01:02:03:04", 0, 0, 0, 0, 0, 0); doParseDateOrTime(UNPARSABLE, "2012-04-09TT12:45:00", 0, 0, 0, 0, 0, 0); } @Test public void testGetLastDay() { assertEquals(-1, getLastDay(2013, -1)); assertEquals(31, getLastDay(2013, 1)); assertEquals(28, getLastDay(2013, 2)); assertEquals(31, getLastDay(2013, 3)); assertEquals(30, getLastDay(2013, 4)); assertEquals(31, getLastDay(2013, 5)); assertEquals(30, getLastDay(2013, 6)); assertEquals(31, getLastDay(2013, 7)); assertEquals(31, getLastDay(2013, 8)); assertEquals(30, getLastDay(2013, 9)); assertEquals(31, getLastDay(2013, 10)); assertEquals(30, getLastDay(2013, 11)); assertEquals(31, getLastDay(2013, 12)); assertEquals(-1, getLastDay(2013, 13)); // Feb, by 400 assertEquals(29, getLastDay(2000, 2)); // Feb, not by 400, by 100 assertEquals(28, getLastDay(1900, 2)); // Feb, not by 400, not by 100, by 4 assertEquals(29, getLastDay(1904, 2)); } @Test public void testParseAndEncodeDate() { // Assumed to be convenience around parse + encode, just sanity check assertEquals(MDateAndTime.encodeDate(2013, 1, 30), parseAndEncodeDate("13-01-30")); assertEquals(MDateAndTime.encodeDate(2013, 1, 30), parseAndEncodeDate("2013-01-30")); assertEquals(MDateAndTime.encodeDate(2013, 1, 30), parseAndEncodeDate("2013-01-30 10:11:12")); } @Test public void testParseAndEncodeDateTime() { // Assumed to be convenience around + encode, just sanity check assertEquals(MDateAndTime.encodeDateTime(2013, 1, 30, 0, 0, 0), parseAndEncodeDateTime("13-01-30")); assertEquals(MDateAndTime.encodeDateTime(2013, 1, 30, 0, 0, 0), parseAndEncodeDateTime("2013-01-30")); } @Test public void testParseTimeZone() { assertEquals(DateTimeZone.forOffsetHoursMinutes(0, 0), parseTimeZone("0:0")); assertEquals(DateTimeZone.forOffsetHoursMinutes(0, 0), parseTimeZone("00:00")); assertEquals(DateTimeZone.forOffsetHoursMinutes(5, 20), parseTimeZone("+05:20")); assertEquals(DateTimeZone.forOffsetHoursMinutes(-5, 45), parseTimeZone("-05:45")); assertEquals(DateTimeZone.forOffsetHoursMinutes(0, 0), parseTimeZone("UTC")); assertEquals(DateTimeZone.forID("MET"), parseTimeZone("met")); assertEquals(DateTimeZone.forID("MET"), parseTimeZone("MET")); assertEquals(DateTimeZone.forID("America/Los_Angeles"), parseTimeZone("America/Los_Angeles")); try { parseTimeZone("asdf"); } catch(InvalidDateFormatException e) { // None } try { parseTimeZone("00x:00y"); } catch(InvalidDateFormatException e) { // None } } @Test public void testParseDate_long() { // Assumed to be implemented with parseDateTime. // Sanity arrayEquals(dt(0), parseDate(0)); arrayEquals(dt(1995, 5, 1), parseDate(19950501)); // But ignores HH:MM:SS arrayEquals(dt(1995, 5, 1), parseDate(19950501101112L)); } @Test public void testParseDateTime_long() { arrayEquals(dt(0), parseDateTime(0)); try { parseDateTime(100); fail("expected invalid"); } catch(InvalidDateFormatException e) { // Expected } arrayEquals(dt(2000, 5, 1), parseDateTime(501)); arrayEquals(dt(2005, 5, 1), parseDateTime(50501)); // Defensible arrayEquals(dt(1995, 5, 1), parseDateTime(950501)); arrayEquals(dt(1995, 5, 1), parseDateTime(19950501)); arrayEquals(dt(1995, 12, 31), parseDateTime(19951231)); arrayEquals(dt(2000, 1, 1), parseDateTime(20000101)); arrayEquals(dt(9999, 12, 31), parseDateTime(99991231)); // And zeros arrayEquals(dt(2000, 0, 0), parseDateTime(20000000)); arrayEquals(dt(2000, 0, 1), parseDateTime(20000001)); arrayEquals(dt(2000, 1, 0), parseDateTime(20000100)); arrayEquals(dt(2000, 3, 0), parseDateTime(20000300)); arrayEquals(dt(1999, 3, 0), parseDateTime(19990300)); // Catches invalid try { parseDateTime(20000231); fail("expected invalid"); } catch(InvalidDateFormatException e) { // Expected } arrayEquals(dt(110, 11, 12, 0, 0, 0), parseDateTime(1101112)); arrayEquals(dt(1995, 5, 1, 10, 11, 12), parseDateTime(950501101112L)); arrayEquals(dt(1995, 5, 1, 10, 11, 12), parseDateTime(19950501101112L)); } @Test public void testIsValidDate() { assertEquals(true, isValidDate_Zeros(dt(0, 0, 0))); assertEquals(false, isValidDate_NoZeros(dt(0, 0, 0))); assertEquals(false, isValidDate_NoZeros(dt(2013, 0, 0))); assertEquals(false, isValidDate_NoZeros(dt(2013, 1, 0))); assertEquals(true, isValidDate_NoZeros(dt(2013, 1, 31))); assertEquals(true, isValidDate(dt(0, 1, 31), ZeroFlag.YEAR)); assertEquals(false, isValidDate(dt(2013, 0, 31), ZeroFlag.YEAR)); assertEquals(false, isValidDate(dt(2013, 1, 0), ZeroFlag.YEAR)); assertEquals(true, isValidDate(dt(2013, 0, 31), ZeroFlag.MONTH)); assertEquals(false, isValidDate(dt(0, 1, 31), ZeroFlag.MONTH)); assertEquals(false, isValidDate(dt(2013, 1, 0), ZeroFlag.MONTH)); assertEquals(true, isValidDate(dt(2013, 1, 0), ZeroFlag.DAY)); assertEquals(false, isValidDate(dt(0, 1, 31), ZeroFlag.DAY)); assertEquals(false, isValidDate(dt(2013, 0, 31), ZeroFlag.DAY)); } @Test public void testIsValidHrMinSec() { assertEquals(true, isValidHrMinSec(0, 0, 0, false, false)); assertEquals(true, isValidHrMinSec(0, 0, 0, false, true)); assertEquals(true, isValidHrMinSec(0, 0, 0, true, false)); assertEquals(false, isValidHrMinSec(0, 0, 60, true, true)); assertEquals(false, isValidHrMinSec(0, 0, 60, true, false)); assertEquals(false, isValidHrMinSec(0, 60, 0, true, true)); assertEquals(false, isValidHrMinSec(0, 60, 0, true, false)); assertEquals(true, isValidHrMinSec(23, 0, 0, true, true)); assertEquals(true, isValidHrMinSec(23, 0, 0, true, false)); assertEquals(false, isValidHrMinSec(24, 0, 0, true, true)); assertEquals(true, isValidHrMinSec(24, 0, 0, true, false)); assertEquals(false, isValidHrMinSec(0, 0, -1, true, true)); assertEquals(false, isValidHrMinSec(0, -1, 0, true, true)); assertEquals(false, isValidHrMinSec(-1, 0, 0, true, true)); assertEquals(true, isValidHrMinSec(0, 0, -1, true, false)); assertEquals(true, isValidHrMinSec(0, -1, 0, true, false)); assertEquals(true, isValidHrMinSec(-1, 0, 0, true, false)); assertEquals(false, isValidHrMinSec(-1, -1, 0, true, false)); assertEquals(false, isValidHrMinSec(-1, -1, -1, true, false)); assertEquals(false, isValidHrMinSec(900, 0, 0, true, false)); assertEquals(true, isValidHrMinSec(900, 0, 0, false, false)); } @Test public void testTimeToString() { assertEquals("00:00:00", timeToString(0, 0, 0)); assertEquals("-01:10:10", timeToString(-1, 10, 10)); assertEquals("838:59:59", timeToString(838, 59, 59)); } private static void arrayEquals(long[] expected, long[] actual) { assertEquals(Arrays.toString(expected), Arrays.toString(actual)); } private static void doParseDateOrTime(StringType expectedType, String st, long... expected) { long[] actual = new long[6]; StringType actualType = parseDateOrTime(st, actual); assertEquals("Type: ", expectedType, actualType); assertEquals(Arrays.toString(expected), Arrays.toString(actual)); } private static long[] dt(long... vals) { return Arrays.copyOf(vals, 6); } }