org.apache.cassandra.serializers.TimestampSerializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cassandra-all Show documentation
Show all versions of cassandra-all Show documentation
The Apache Cassandra Project develops a highly scalable second-generation distributed database, bringing together Dynamo's fully distributed design and Bigtable's ColumnFamily-based data model.
/*
* 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 io.netty.util.concurrent.FastThreadLocal;
import org.apache.cassandra.db.marshal.ValueAccessor;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.text.Format;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
public class TimestampSerializer extends TypeSerializer
{
private static final List dateFormatters = generateFormatters();
private static List generateFormatters()
{
List formatters = new ArrayList<>();
final String[] dateTimeFormats = new String[]
{
"y-M-d'T'H:m[:s]",
"y-M-d H:m[:s]"
};
final String[] offsetFormats = new String[]
{
" z",
" zzzz",
" X",
"X",
"XXX",
};
for (String dateTimeFormat: dateTimeFormats)
{
// local date time
formatters.add(
new DateTimeFormatterBuilder()
.appendPattern(dateTimeFormat)
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 9, true)
.toFormatter()
.withZone(ZoneId.systemDefault()));
for (String offset : offsetFormats)
{
formatters.add(
new DateTimeFormatterBuilder()
.appendPattern(dateTimeFormat)
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 9, true)
.appendPattern(offset)
.toFormatter()
);
}
}
for (String offset: offsetFormats)
{
formatters.add(
new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd")
.appendPattern(offset)
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter()
);
}
// local date
formatters.add(
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_DATE)
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter().withZone(ZoneId.systemDefault()));
return formatters;
}
private static final Pattern timestampPattern = Pattern.compile("^-?\\d+$");
private static final FastThreadLocal FORMATTER_UTC = new FastThreadLocal()
{
protected java.text.Format initialValue()
{
return new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter()
.withZone(ZoneId.of("UTC"))
.toFormat();
}
};
private static final FastThreadLocal FORMATTER_TO_JSON = new FastThreadLocal()
{
protected java.text.Format initialValue()
{
return new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd HH:mm:ss.SSSX")
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter()
.withZone(ZoneId.of("UTC"))
.toFormat();
}
};
public static final TimestampSerializer instance = new TimestampSerializer();
public Date deserialize(V value, ValueAccessor accessor)
{
return accessor.isEmpty(value) ? null : new Date(accessor.toLong(value));
}
public ByteBuffer serialize(Date value)
{
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value.getTime());
}
public static long dateStringToTimestamp(String source) throws MarshalException
{
if (source.equalsIgnoreCase("now"))
return System.currentTimeMillis();
// Milliseconds since epoch?
if (timestampPattern.matcher(source).matches())
{
try
{
return Long.parseLong(source);
}
catch (NumberFormatException e)
{
throw new MarshalException(String.format("Unable to make long (for date) from: '%s'", source), e);
}
}
for (DateTimeFormatter fmt: dateFormatters)
{
try
{
return ZonedDateTime.parse(source, fmt).toInstant().toEpochMilli();
}
catch (DateTimeParseException e)
{
continue;
}
}
throw new MarshalException(String.format("Unable to parse a date/time from '%s'", source));
}
public static Format getJsonDateFormatter()
{
return FORMATTER_TO_JSON.get();
}
public void validate(V value, ValueAccessor accessor) throws MarshalException
{
if (accessor.size(value) != 8 && !accessor.isEmpty(value))
throw new MarshalException(String.format("Expected 8 or 0 byte long for date (%d)", accessor.size(value)));
}
public String toString(Date value)
{
return toStringUTC(value);
}
public String toStringUTC(Date value)
{
return value == null ? "" : FORMATTER_UTC.get().format(value.toInstant());
}
public Class getType()
{
return Date.class;
}
/**
* Builds CQL literal for a timestamp using time zone UTC and fixed date format.
* @see #FORMATTER_UTC
*/
@Override
public String toCQLLiteral(ByteBuffer buffer)
{
return buffer == null || !buffer.hasRemaining()
? "null"
: FORMATTER_UTC.get().format(deserialize(buffer).toInstant());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy