| /** |
| * 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.cassandra.serializers; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.ArrayList; |
| |
| import org.junit.Test; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| public class TimestampSerializerTest |
| { |
| public static final long ONE_SECOND = 1000L; |
| public static final long ONE_MINUTE = 60 * ONE_SECOND; |
| public static final long ONE_HOUR = 60 * ONE_MINUTE; |
| public static final long ONE_DAY = 24 * ONE_HOUR; |
| public static final long BASE_OFFSET = TimestampSerializer.dateStringToTimestamp("1970-01-01"); |
| |
| @Test |
| public void testFormatResults() throws MarshalException |
| { |
| validateStringTimestamp("1970-01-01 00:00", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01 00:01", BASE_OFFSET + ONE_MINUTE); |
| validateStringTimestamp("1970-01-01 01:00", BASE_OFFSET + ONE_HOUR); |
| validateStringTimestamp("1970-01-02 00:00", BASE_OFFSET + ONE_DAY); |
| validateStringTimestamp("1970-01-02 00:00 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01 00:01+01", ONE_MINUTE - ONE_HOUR); |
| validateStringTimestamp("1970-01-01 01:00+0100", ONE_HOUR - ONE_HOUR); |
| validateStringTimestamp("1970-01-02 00:00+01:00", ONE_DAY - ONE_HOUR); |
| validateStringTimestamp("1970-01-01 01:00-0200", ONE_HOUR + 2 * ONE_HOUR); |
| validateStringTimestamp("1970-01-01 01:00Z", ONE_HOUR); |
| |
| validateStringTimestamp("1970-01-01 00:00:00", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01 00:00:01", BASE_OFFSET + ONE_SECOND); |
| validateStringTimestamp("1970-01-01 00:01:00", BASE_OFFSET + ONE_MINUTE); |
| validateStringTimestamp("1970-01-01 01:00:00", BASE_OFFSET + ONE_HOUR); |
| validateStringTimestamp("1970-01-02 00:00:00", BASE_OFFSET + ONE_DAY); |
| validateStringTimestamp("1970-01-02 00:00:00 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01 00:01:00+01", ONE_MINUTE - ONE_HOUR); |
| validateStringTimestamp("1970-01-01 01:00:00+0100", ONE_HOUR - ONE_HOUR); |
| validateStringTimestamp("1970-01-02 00:00:00+01:00", ONE_DAY - ONE_HOUR); |
| validateStringTimestamp("1970-01-01 01:00:00-0200", ONE_HOUR + 2 * ONE_HOUR); |
| validateStringTimestamp("1970-01-01 01:00:00Z", ONE_HOUR); |
| |
| validateStringTimestamp("1970-01-01 00:00:00.000", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01 00:00:00.000", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01 00:00:01.000", BASE_OFFSET + ONE_SECOND); |
| validateStringTimestamp("1970-01-01 00:01:00.000", BASE_OFFSET + ONE_MINUTE); |
| validateStringTimestamp("1970-01-01 01:00:00.000", BASE_OFFSET + ONE_HOUR); |
| validateStringTimestamp("1970-01-02 00:00:00.000", BASE_OFFSET + ONE_DAY); |
| validateStringTimestamp("1970-01-02 00:00:00.000 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01 00:00:00.100 UTC", 100L); |
| validateStringTimestamp("1970-01-01 00:01:00.001+01", ONE_MINUTE - ONE_HOUR + 1); |
| validateStringTimestamp("1970-01-01 01:00:00.002+0100", ONE_HOUR - ONE_HOUR + 2); |
| validateStringTimestamp("1970-01-02 00:00:00.003+01:00", ONE_DAY - ONE_HOUR + 3); |
| validateStringTimestamp("1970-01-01 01:00:00.004-0200", ONE_HOUR + 2 * ONE_HOUR + 4); |
| validateStringTimestamp("1970-01-01 01:00:00.004Z", ONE_HOUR + 4); |
| |
| validateStringTimestamp("1970-01-01T00:00", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01T00:01", BASE_OFFSET + ONE_MINUTE); |
| validateStringTimestamp("1970-01-01T01:00", BASE_OFFSET + ONE_HOUR); |
| validateStringTimestamp("1970-01-02T00:00", BASE_OFFSET + ONE_DAY); |
| validateStringTimestamp("1970-01-02T00:00 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01T00:01+01", ONE_MINUTE - ONE_HOUR); |
| validateStringTimestamp("1970-01-01T01:00+0100", ONE_HOUR - ONE_HOUR); |
| validateStringTimestamp("1970-01-02T00:00+01:00", ONE_DAY - ONE_HOUR); |
| validateStringTimestamp("1970-01-01T01:00-0200", ONE_HOUR + 2 * ONE_HOUR); |
| validateStringTimestamp("1970-01-01T01:00Z", ONE_HOUR); |
| |
| validateStringTimestamp("1970-01-01T00:00:00", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01T00:00:01", BASE_OFFSET + ONE_SECOND); |
| validateStringTimestamp("1970-01-01T00:01:00", BASE_OFFSET + ONE_MINUTE); |
| validateStringTimestamp("1970-01-01T01:00:00", BASE_OFFSET + ONE_HOUR); |
| validateStringTimestamp("1970-01-02T00:00:00", BASE_OFFSET + ONE_DAY); |
| validateStringTimestamp("1970-01-02T00:00:00 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01T00:01:00+01", ONE_MINUTE - ONE_HOUR); |
| validateStringTimestamp("1970-01-01T01:00:00+0100", ONE_HOUR - ONE_HOUR); |
| validateStringTimestamp("1970-01-02T00:00:00+01:00", ONE_DAY - ONE_HOUR); |
| validateStringTimestamp("1970-01-01T01:00:00-0200", ONE_HOUR + 2 * ONE_HOUR); |
| validateStringTimestamp("1970-01-01T01:00:00Z", ONE_HOUR); |
| |
| validateStringTimestamp("1970-01-01T00:00:00.000", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01T00:00:00.000", BASE_OFFSET); |
| validateStringTimestamp("1970-01-01T00:00:01.000", BASE_OFFSET + ONE_SECOND); |
| validateStringTimestamp("1970-01-01T00:01:00.000", BASE_OFFSET + ONE_MINUTE); |
| validateStringTimestamp("1970-01-01T01:00:00.000", BASE_OFFSET + ONE_HOUR); |
| validateStringTimestamp("1970-01-02T00:00:00.000", BASE_OFFSET + ONE_DAY); |
| validateStringTimestamp("1970-01-02T00:00:00.000 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01T00:00:00.100 UTC", 100L); |
| validateStringTimestamp("1970-01-01T00:01:00.001+01", ONE_MINUTE - ONE_HOUR + 1); |
| validateStringTimestamp("1970-01-01T01:00:00.002+0100", ONE_HOUR - ONE_HOUR + 2); |
| validateStringTimestamp("1970-01-02T00:00:00.003+01:00", ONE_DAY - ONE_HOUR + 3); |
| validateStringTimestamp("1970-01-01T01:00:00.004-0200", ONE_HOUR + 2 * ONE_HOUR + 4); |
| validateStringTimestamp("1970-01-01T01:00:00.004Z", ONE_HOUR + 4); |
| |
| validateStringTimestamp("1970-01-01", BASE_OFFSET); |
| validateStringTimestamp("1970-01-02 UTC", ONE_DAY); |
| validateStringTimestamp("1970-01-01+01", -ONE_HOUR); |
| validateStringTimestamp("1970-01-01+0100", -ONE_HOUR); |
| validateStringTimestamp("1970-01-02+01:00", ONE_DAY - ONE_HOUR); |
| validateStringTimestamp("1970-01-01-0200", 2 * ONE_HOUR); |
| validateStringTimestamp("1970-01-01Z", 0L); |
| } |
| |
| @Test |
| public void testGeneralTimeZoneFormats() |
| { |
| // Central Standard Time; CST, GMT-06:00 |
| final long cstOffset = 6 * ONE_HOUR; |
| validateStringTimestamp("1970-01-01 00:00:00 Central Standard Time", cstOffset); |
| validateStringTimestamp("1970-01-01 00:00:00 CST", cstOffset); |
| validateStringTimestamp("1970-01-01 00:00:00 -0600", cstOffset); |
| validateStringTimestamp("1970-01-01 00:00:00-0600", cstOffset); |
| validateStringTimestamp("1970-01-01T00:00:00 GMT-06:00", cstOffset); |
| validateStringTimestamp("1970-01-01T00:00:00 -0600", cstOffset); |
| validateStringTimestamp("1970-01-01T00:00:00-0600", cstOffset); |
| } |
| |
| @Test |
| public void testVaryingFractionalPrecision() // CASSANDRA-15976 |
| { |
| validateStringTimestamp("1970-01-01 00:00:00.10 UTC", 100L); |
| validateStringTimestamp("1970-01-01 00:00:00.1+00", 100L); |
| validateStringTimestamp("1970-01-01T00:00:00.10-0000", 100L); |
| validateStringTimestamp("1970-01-01T00:00:00.1Z", 100L); |
| validateStringTimestamp("1970-01-01 00:00:00.1 Central Standard Time", 6 * ONE_HOUR + 100L); |
| validateStringTimestamp("1970-01-01 00:00:00.10+00:00", 100L); |
| validateStringTimestamp("1970-01-01T00:00:00.1", BASE_OFFSET + 100L); |
| validateStringTimestamp("1970-01-01T00:00:00.10-00:00", 100L); |
| } |
| |
| @Test |
| public void testZeroPadding() // CASSANDRA-16105 |
| { |
| long expected = ONE_HOUR + ONE_MINUTE + ONE_SECOND; |
| validateStringTimestamp("1970-01-01 01:01:01Z", expected); |
| validateStringTimestamp("1970-1-1 1:1:1Z", expected); |
| validateStringTimestamp("1970-01-01 01:01:01", BASE_OFFSET + expected); |
| validateStringTimestamp("1970-1-1 1:1:1", BASE_OFFSET + expected); |
| |
| expected = -31556905139000L; |
| validateStringTimestamp("0970-01-01 01:01:01Z", expected); |
| validateStringTimestamp("970-1-1 1:1:1Z", expected); |
| |
| expected = 10*ONE_MINUTE + 100L; |
| validateStringTimestamp("1970-01-01T0:0000000010:0.1Z", expected); |
| validateStringTimestamp("0001970-01-01T0:010:0.1Z", expected); |
| validateStringTimestamp("1970-1-1T0:10:0.1Z", expected); |
| validateStringTimestamp("1970-0001-0001T0:010:0.1Z", expected); |
| |
| validateStringTimestamp("1970-1-01T1:1Z", ONE_HOUR + ONE_MINUTE); |
| validateStringTimestamp("1970-1-01T1:1", BASE_OFFSET + ONE_HOUR + ONE_MINUTE); |
| } |
| |
| @Test |
| public void testInvalidTimezones() |
| { |
| List<String> timestamps = new ArrayList<String>( |
| Arrays.asList( |
| "1970-01-01 00:00:00 xentral Standard Time", |
| "1970-01-01 00:00:00-060" |
| ) |
| ); |
| expectStringTimestampsExcept(timestamps); |
| } |
| |
| @Test |
| public void testInvalidFormat() |
| { |
| List<String> timestamps = new ArrayList<String>( |
| Arrays.asList( |
| "1970-01-01 00:00:00andsomeextra", |
| "prefix1970-01-01 00:00:00", |
| "1970-01-01 00.56", |
| "1970-01-0100:00:00" |
| ) |
| ); |
| expectStringTimestampsExcept(timestamps); |
| } |
| |
| @Test |
| public void testNumeric() |
| { |
| // now (positive |
| final long now = System.currentTimeMillis(); |
| assertEquals(now, TimestampSerializer.dateStringToTimestamp(Long.toString(now))); |
| |
| // negative |
| final long then = -11234L; |
| assertEquals(then, TimestampSerializer.dateStringToTimestamp(Long.toString(then))); |
| |
| // overflows |
| for (Long l: Arrays.asList(Long.MAX_VALUE, Long.MIN_VALUE)) |
| { |
| try |
| { |
| TimestampSerializer.dateStringToTimestamp(Long.toString(l) + "1"); |
| fail("Expected exception was not raised while parsing overflowed long."); |
| } |
| catch (MarshalException e) |
| { |
| continue; |
| } |
| } |
| } |
| |
| @Test |
| public void testNow() |
| { |
| final long threshold = 5; |
| final long now = System.currentTimeMillis(); |
| final long parsed = TimestampSerializer.dateStringToTimestamp("now"); |
| assertTrue("'now' timestamp not within expected tolerance.", now <= parsed && parsed <= now + threshold); |
| } |
| |
| private void validateStringTimestamp(String s, long expected) |
| { |
| try |
| { |
| long ts = TimestampSerializer.dateStringToTimestamp(s); |
| assertEquals( "Failed to parse expected timestamp value from " + s, expected, ts); |
| } |
| catch (MarshalException e) |
| { |
| fail(String.format("Failed to parse \"%s\" as timestamp.", s)); |
| } |
| } |
| |
| private void expectStringTimestampsExcept(List<String> timeStrings) |
| { |
| for (String s: timeStrings) |
| { |
| try |
| { |
| TimestampSerializer.dateStringToTimestamp(s); |
| fail(String.format("Parsing succeeded while expecting failure from \"%s\"", s)); |
| } |
| catch(MarshalException e) |
| { |
| continue; |
| } |
| |
| } |
| } |
| } |