/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hive.common.util; import java.sql.Timestamp; import java.util.Arrays; import java.util.List; import static org.junit.Assert.*; import org.junit.Test; public class TestTimestampParser { public static class ValidTimestampCase { String strValue; Timestamp expectedValue; public ValidTimestampCase(String strValue, Timestamp expectedValue) { this.strValue = strValue; this.expectedValue = expectedValue; } } static void testValidCases(TimestampParser tp, ValidTimestampCase[] validCases) { for (ValidTimestampCase validCase : validCases) { Timestamp ts = tp.parseTimestamp(validCase.strValue); assertEquals("Parsing " + validCase.strValue, validCase.expectedValue, ts); } } static void testInvalidCases(TimestampParser tp, String[] invalidCases) { for (String invalidString : invalidCases) { try { Timestamp ts = tp.parseTimestamp(invalidString); fail("Expected exception parsing " + invalidString + ", but parsed value to " + ts); } catch (IllegalArgumentException err) { // Exception expected } } } @Test public void testDefault() { // No timestamp patterns, should default to normal timestamp format TimestampParser tp = new TimestampParser(); ValidTimestampCase[] validCases = { new ValidTimestampCase("1945-12-31 23:59:59.0", Timestamp.valueOf("1945-12-31 23:59:59.0")), new ValidTimestampCase("1945-12-31 23:59:59.1234", Timestamp.valueOf("1945-12-31 23:59:59.1234")), new ValidTimestampCase("1970-01-01 00:00:00", Timestamp.valueOf("1970-01-01 00:00:00")), }; String[] invalidCases = { "1945-12-31T23:59:59", "12345", }; testValidCases(tp, validCases); testInvalidCases(tp, invalidCases); } @Test public void testPattern1() { // Joda pattern matching expects fractional seconds length to match // the number of 'S' in the pattern. So if you want to match .1, .12, .123, // you need 3 different patterns with .S, .SS, .SSS String[] patterns = { // ISO-8601 timestamps "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.S", "yyyy-MM-dd'T'HH:mm:ss.SS", "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSSS", }; TimestampParser tp = new TimestampParser(patterns); ValidTimestampCase[] validCases = { new ValidTimestampCase("1945-12-31T23:59:59.0", Timestamp.valueOf("1945-12-31 23:59:59.0")), new ValidTimestampCase("2001-01-01 00:00:00.100", Timestamp.valueOf("2001-01-01 00:00:00.100")), new ValidTimestampCase("2001-01-01 00:00:00.001", Timestamp.valueOf("2001-01-01 00:00:00.001")), // Joda parsing only supports up to millisecond precision new ValidTimestampCase("1945-12-31T23:59:59.1234", Timestamp.valueOf("1945-12-31 23:59:59.123")), new ValidTimestampCase("1970-01-01T00:00:00", Timestamp.valueOf("1970-01-01 00:00:00")), new ValidTimestampCase("1970-4-5T6:7:8", Timestamp.valueOf("1970-04-05 06:07:08")), // Default timestamp format still works? new ValidTimestampCase("2001-01-01 00:00:00", Timestamp.valueOf("2001-01-01 00:00:00")), new ValidTimestampCase("1945-12-31 23:59:59.1234", Timestamp.valueOf("1945-12-31 23:59:59.1234")), }; String[] invalidCases = { "1945-12-31-23:59:59", "1945-12-31T23:59:59.12345", // our pattern didn't specify 5 decimal places "12345", }; testValidCases(tp, validCases); testInvalidCases(tp, invalidCases); } @Test public void testMillisParser() { String[] patterns = { "millis", // Also try other patterns "yyyy-MM-dd'T'HH:mm:ss", }; TimestampParser tp = new TimestampParser(patterns); ValidTimestampCase[] validCases = { new ValidTimestampCase("0", new Timestamp(0)), new ValidTimestampCase("-1000000", new Timestamp(-1000000)), new ValidTimestampCase("1420509274123", new Timestamp(1420509274123L)), new ValidTimestampCase("1420509274123.456789", new Timestamp(1420509274123L)), // Other format pattern should also work new ValidTimestampCase("1945-12-31T23:59:59", Timestamp.valueOf("1945-12-31 23:59:59")), }; String[] invalidCases = { "1945-12-31-23:59:59", "1945-12-31T23:59:59.12345", // our pattern didn't specify 5 decimal places "1420509274123-", }; testValidCases(tp, validCases); testInvalidCases(tp, invalidCases); } @Test public void testPattern2() { // Pattern does not contain all date fields String[] patterns = { "HH:mm", "MM:dd:ss", }; TimestampParser tp = new TimestampParser(patterns); ValidTimestampCase[] validCases = { new ValidTimestampCase("05:06", Timestamp.valueOf("1970-01-01 05:06:00")), new ValidTimestampCase("05:06:07", Timestamp.valueOf("1970-05-06 00:00:07")), }; String[] invalidCases = { "1945-12-31T23:59:59", "1945:12:31-", "12345", }; testValidCases(tp, validCases); testInvalidCases(tp, invalidCases); } }