blob: ac63f31d6ac148b4491230e0ab19769d87534c9b [file] [log] [blame]
/**
* 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;
}
}
}
}