/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
/**
*
*/
package org.csstudio.dal;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* This is timestamp object with nanosecond resolution. It holds two long values. One is with millisoecnd
* resolution and represents Java standart UTC format. Second long value is with nanosecond resolution
* and its absolute value is lower than 1ms or 1000000ns.
* @author ikriznar
*
*/
public final class Timestamp implements Comparable<Timestamp>
{
private long milliseconds;
private long nanoseconds;
private final static SimpleDateFormat formatFull = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS");
private final static SimpleDateFormat formatDateTimeSeconds = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss");
private final static SimpleDateFormat formatDateTime = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm");
private final static SimpleDateFormat formatDate = new SimpleDateFormat(
"yyyy-MM-dd");
public enum Format
{
/** Format to ISO with "YYYY-MM-DD". */
Date,
/** Format to ISO with "YYYY-MM-DDTHH:MM". */
DateTime,
/** Format to ISO with "YYYY-MM-DDTHH:MM:SS". */
DateTimeSeconds,
/** Format to ISO with full precision "YYYY/MM/DD HH:MM:SS.000000000". */
Full;
}
private final static long currentSecondInNano()
{
long l = System.nanoTime();
return l - ((l / 1000000000) * 1000000000);
}
/**
* Default constructor, uses system time for initialization.
*
*/
public Timestamp()
{
this((System.currentTimeMillis() / 1000) * 1000, currentSecondInNano());
}
/**
* Creates timestamp representing provided values. If nanoseconds exceed 1000000 or -1000000 then they are
* truncated to nanoseconds within millisecond and millisecond is corrected.
* @param milli
* @param nano
*/
public Timestamp(long milli, long nano)
{
// correction if there is more nanoseconds than it fits in
if (nano >= 1000000) {
long t = nano / 1000000;
milliseconds = milli + t;
nanoseconds = nano - t * 1000000;
} else if (nano <= -1000000) {
long t = nano / 1000000;
milliseconds = milli + t - 1;
nanoseconds = nano - t * 1000000 + 1000000;
} else if (nano < 0) {
milliseconds = milli - 1;
nanoseconds = nano + 1000000;
} else {
milliseconds = milli;
nanoseconds = nano;
}
}
/**
* Returns time in milliseconds since epoch (standard Java UTC time, as returned by System.currentTimeMillis())
* @return Returns the milliseconds.
*/
public long getMilliseconds()
{
return milliseconds;
}
/**
* @return Returns the nanoseconds within the millisecond.
*/
public long getNanoseconds()
{
return nanoseconds;
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(T)
*/
@Override
public int compareTo(Timestamp o)
{
if (o instanceof Timestamp) {
Timestamp t = (Timestamp)o;
long d = milliseconds - t.milliseconds;
if (d != 0) {
return (int)d;
}
d = nanoseconds - t.nanoseconds;
return (int)d;
}
return 0;
}
/**
* Returns time in nanoseconds since epoch. Not that this in only usefull for calculating
* time difference for up to 292 years (2<sup>63</sup> nanoseconds) since this is maximum time possible in
* nanoseconds due to long value range overflow.
* @return up to approx. 292 years big nano time
*/
public long toNanoTime()
{
return milliseconds * 1000000 + nanoseconds;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (obj instanceof Timestamp) {
Timestamp t = (Timestamp)obj;
return t.milliseconds == milliseconds
&& t.nanoseconds == nanoseconds;
}
return false;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuffer sb = new StringBuffer(32);
formatFull.format(new Date(milliseconds), sb,
new FieldPosition(DateFormat.FULL));
if (nanoseconds < 100000) {
sb.append('0');
if (nanoseconds < 10000) {
sb.append('0');
if (nanoseconds < 1000) {
sb.append('0');
if (nanoseconds < 100) {
sb.append('0');
if (nanoseconds < 10) {
sb.append('0');
}
}
}
}
}
sb.append(nanoseconds);
return sb.toString();
}
/**
* @return Returns timestamp as string formated as specified.
*/
public String toString(Format format)
{
StringBuffer sb = new StringBuffer(32);
switch (format.ordinal()) {
case 0:
formatDate.format(new Date(milliseconds), sb,
new FieldPosition(DateFormat.FULL));
return sb.toString();
case 1:
formatDateTime.format(new Date(milliseconds), sb,
new FieldPosition(DateFormat.FULL));
return sb.toString();
case 2:
formatDateTimeSeconds.format(new Date(milliseconds), sb,
new FieldPosition(DateFormat.FULL));
return sb.toString();
default:
return toString();
}
}
/** Get seconds since epoch, i.e. 1 January 1970 0:00 UTC.
* @return Seconds since 1970.
*/
public long getSeconds() {
return milliseconds/1000L;
}
/**
* Converts timestamp to double.
* @return Return seconds and fractional nanoseconds.
*/
public double toDouble() {
return (double)milliseconds/1000.0+(double)nanoseconds/1000000000.0;
}
/**
* @return Returns <code>true</code> if time fields > 0.
*/
public boolean isValid() {
return milliseconds>0;
}
/**
* @return Returns <code>true</code> if this time stamp is greater than
* the <code>other</code> time stamp.
* @param other Other time stamp
*/
public boolean isGreaterThan(final Timestamp other) {
if (milliseconds<other.milliseconds) {
return false;
}
if (milliseconds==other.milliseconds) {
return nanoseconds>other.nanoseconds;
}
return true;
}
/**
* @return Returns <code>true</code> if this time stamp is greater than or
* equal to the <code>other</code> time stamp.
* @param other Other time stamp
*/
public boolean isGreaterOrEqual(final Timestamp other) {
if (milliseconds<other.milliseconds) {
return false;
}
if (milliseconds==other.milliseconds) {
return nanoseconds>=other.nanoseconds;
}
return true;
}
/**
* @return Returns <code>true</code> if this time stamp is smaller than
* the <code>other</code> time stamp.
* @param other Other time stamp
*/
public boolean isLessThan(final Timestamp other) {
if (milliseconds>other.milliseconds) {
return false;
}
if (milliseconds==other.milliseconds) {
return nanoseconds<other.nanoseconds;
}
return true;
}
/**
* @return Returns <code>true</code> if this time stamp is smaller than or
* equal to the <code>other</code> time stamp.
* @param other Other time stamp
*/
public boolean isLessOrEqual(final Timestamp other) {
if (milliseconds>other.milliseconds) {
return false;
}
if (milliseconds==other.milliseconds) {
return nanoseconds<=other.nanoseconds;
}
return true;
}
}
/* __oOo__ */