/** * Copyright (c) 2011-2014 Exxeleron GmbH * * Licensed 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 com.exxeleron.qjava; import java.io.Serializable; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Represents q timespan type. */ public final class QTimespan implements DateTime, Serializable { private static final long serialVersionUID = 762296525233866140L; private static final String NULL_STR = "0Nn"; private static final DateFormat dateFormat = new SimpleDateFormat("'D'HH:mm:ss.SSS"); private static final NumberFormat nanosFormatter = new DecimalFormat("000000"); private static final int NANOS_PER_SECOND = 1000000; private static final long NANOS_PER_DAY = Utils.DAY_MILLIS * 1000000; private transient Date datetime; private final Long value; /** * Creates new {@link QTimespan} instance using specified q date value. * * @param value * a count of nanoseconds from midnight */ public QTimespan(final Long value) { this.value = value; } private static long getNanos( final Date datetime ) { final Calendar c = Calendar.getInstance(); c.setTime(datetime); return (long) (c.get(Calendar.MILLISECOND) + 1000 * c.get(Calendar.SECOND) + 60000 * c.get(Calendar.MINUTE) + 3600000 * c.get(Calendar.HOUR_OF_DAY)) * NANOS_PER_SECOND; } /** * Creates new {@link QTimespan} instance using specified {@link Date}. * * @param datetime * {@link Date} to be set */ public QTimespan(final Date datetime) { this.datetime = datetime; if ( datetime != null ) { value = getNanos(datetime); } else { value = Long.MIN_VALUE; } } /** * Returns a count of nanoseconds from midnight. * * @return raw q value */ public Long getValue() { return value; } /** * Converts {@link QTimespan} object to {@link Date} instance. * * @return {@link Date} representing q value. */ public Date toDateTime() { if ( datetime == null && value != Long.MIN_VALUE ) { datetime = new Date(Utils.tzOffsetToQ(Math.abs(value) / NANOS_PER_SECOND + Utils.QEPOCH_MILLIS)); } return datetime; } /** * Returns a String that represents the current {@link QTimespan}. * * @return a String representation of the {@link QTimespan} * @see java.lang.Object#toString() */ @Override public String toString() { final Date dt = toDateTime(); return dt == null ? NULL_STR : (value < 0 ? "-" : "") + (Math.abs(value) / NANOS_PER_DAY) + getDateformat().format(dt) + getNanosformat().format(Math.abs(value) % NANOS_PER_SECOND); } /** * Indicates whether some other object is "equal to" this date. {@link QTimespan} objects are considered equal if * the underlying q raw value is the same for both instances. * * @return <code>true</code> if this object is the same as the obj argument, <code>false</code> otherwise. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals( final Object obj ) { if ( this == obj ) { return true; } if ( !(obj instanceof QTimespan) ) { return false; } return value.equals(((QTimespan) obj).getValue()); } /** * Returns a hash code value for this {@link QTimespan}. * * @return a hash code value for this object * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return value.hashCode(); } /** * Returns a {@link QTimespan} represented by a given string. * * @param date * as {@link String} * @return a {@link QTimespan} instance representing date. * @throws IllegalArgumentException * when date cannot be parsed */ public static QTimespan fromString( final String date ) { try { if ( date == null || date.length() == 0 || date.equals(NULL_STR) ) { return new QTimespan(Long.MIN_VALUE); } else { final long nanos = getNanos(getDateformat().parse(date.substring(date.indexOf("D"), date.lastIndexOf(".") + 3))) + getNanosformat().parse(date.substring(date.lastIndexOf(".") + 3)).longValue(); return new QTimespan(Integer.valueOf(date.substring(0, date.indexOf("D"))) * NANOS_PER_DAY + ('-' == date.charAt(0) ? -1 : 1) * nanos); } } catch ( final Exception e ) { throw new IllegalArgumentException("Cannot parse QTimespan from: " + date, e); } } private static DateFormat getDateformat() { return (DateFormat) dateFormat.clone(); } private static NumberFormat getNanosformat() { return (NumberFormat) nanosFormatter.clone(); } }