blob: a8ec05a0b31e87b15f80291f045387095dd623e3 [file] [log] [blame]
/**
*
*/
package org.apache.rya.indexing;
/*
* 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.
*/
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.codec.binary.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
/**
* Immutable date and time instance returning a human readable key.
* Preserves the Time zone, but not stored in the key.
* Converts fields (hours, etc) correctly for tz=Zulu when stored,
* so the original timezone is not preserved when retrieved.
*
* Uses rfc 3339, which looks like: YYYY-MM-DDThh:mm:ssZ a subset
* of ISO-8601 : https://www.ietf.org/rfc/rfc3339.txt
*
* Limits: All dates and times are assumed to be in the "current era", no BC,
* somewhere between 0000AD and 9999AD.
*
* Resolution: to the second, or millisecond if the optional fraction is used.
*
* This is really a wrapper for Joda DateTime. if you need functionality from
* that wonderful class, simply use t.getAsDateTime().
*
*/
public class TemporalInstantRfc3339 implements TemporalInstant {
private static final long serialVersionUID = -7790000399142290309L;
private final DateTime dateTime;
/**
* Format key like this: YYYY-MM-DDThh:mm:ssZ
*/
public final static DateTimeFormatter FORMATTER = ISODateTimeFormat.dateTimeNoMillis();
public static final Pattern PATTERN = Pattern.compile("\\[(.*)\\,(.*)\\].*");
/**
* New date assumed UTC time zone.
*
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
*/
public TemporalInstantRfc3339(final int year, final int month, final int day, final int hour, final int minute, final int second) {
dateTime = new DateTime(year, month, day, hour, minute, second, DateTimeZone.UTC);
}
/**
* Construct with a Joda/java v8 DateTime;
* TZ is preserved, but not in the key.
*
* @param dateTime
* initialize with this date time. Converted to zulu time zone for key generation.
* @return
*/
public TemporalInstantRfc3339(final DateTime datetime) {
dateTime = datetime;
}
/**
* Get an interval setting beginning and end with this implementation of {@link TemporalInstant}.
* beginning must be less than end.
*
* @param dateTimeInterval String in the form [dateTime1,dateTime2]
*/
public static TemporalInterval parseInterval(final String dateTimeInterval) {
final Matcher matcher = PATTERN.matcher(dateTimeInterval);
if (matcher.find()) {
// Got a date time pair, parse into an interval.
return new TemporalInterval(
new TemporalInstantRfc3339(new DateTime(matcher.group(1))),
new TemporalInstantRfc3339(new DateTime(matcher.group(2))));
}
throw new IllegalArgumentException("Can't parse interval, expecting '[ISO8601dateTime1,ISO8601dateTime2]', actual: "+dateTimeInterval);
}
/**
* if this is older returns -1, equal 0, else 1
*
*/
@Override
public int compareTo(final TemporalInstant that) {
return getAsKeyString().compareTo(that.getAsKeyString());
}
@Override
public byte[] getAsKeyBytes() {
return StringUtils.getBytesUtf8(getAsKeyString());
}
@Override
public String getAsKeyString() {
return dateTime.withZone(DateTimeZone.UTC).toString(FORMATTER);
}
/**
* Readable string, formated local time at {@link DateTimeZone}.
* If the timezone is UTC (Z), it was probably a key from the database.
* If the server and client are in different Time zone, should probably use the client timezone.
*
* Time at specified time zone:
* instant.getAsReadable(DateTimeZone.forID("-05:00")));
* instant.getAsReadable(DateTimeZone.getDefault()));
*
* Use original time zone set in the constructor:
* instant.getAsDateTime().toString(TemporalInstantRfc3339.FORMATTER));
*
*/
@Override
public String getAsReadable(final DateTimeZone dateTimeZone) {
return dateTime.withZone(dateTimeZone).toString(FORMATTER);
}
/**
* Use original time zone set in the constructor, or UTC if from parsing the key.
*/
@Override
public String getAsReadable() {
return dateTime.toString(FORMATTER);
}
/**
* default toString, same as getAsReadable().
*/
@Override
public String toString() {
return getAsReadable();
}
/**
* Show readable time converted to the default timezone.
*/
@Override
public DateTime getAsDateTime() {
return dateTime;
}
/**
* Minimum Date, used for infinitely past.
*/
private static final TemporalInstant MINIMUM = new TemporalInstantRfc3339(new DateTime(Long.MIN_VALUE));
/**
* maximum date/time is used for infinitely in the future.
*/
private static final TemporalInstant MAXIMUM = new TemporalInstantRfc3339(new DateTime(Long.MAX_VALUE));
/**
* infinite past date.
* @return an instant that will compare as NEWER than anything but itself.
*/
public static TemporalInstant getMinimumInstance() {
return MINIMUM;
}
/**
* infinite future date.
* @return an instant that will compare as OLDER than anything but itself
*/
public static TemporalInstant getMaximumInstance() {
return MAXIMUM;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return getAsKeyString().hashCode();
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TemporalInstantRfc3339 other = (TemporalInstantRfc3339) obj;
return (getAsKeyString().equals(other.getAsKeyString()));
}
}