📄 timestamp.java
字号:
/*------------------------------------------------------------------------------Name: Timestamp.javaProject: xmlBlaster.orgCopyright: xmlBlaster.org, see xmlBlaster-LICENSE fileComment: Create unique timestamp------------------------------------------------------------------------------*/package org.xmlBlaster.util;/** * High performing timestamp class, time elapsed since 1970, the nanos are simulated * as a unique counter. * <br /> * The counter is rewound on any millisecond step. * <br /> * Timestamp objects are immutable - a Timstamp can not be changed once it is created. * <br /> * Guarantees that any created Timestamp instance is unique in the current * Java Virtual Machine (and Classloader). * <br /><br /> * Fails only if * <ul> * <li>a CPU can create more than 999999 Timestamp instances per millisecond</li> * <li>In ~ 288 years when Long.MAX_VALUE = 9223372036854775807 overflows (current value is 1013338358124000008)</li> * </ul> * A typical output is:<br /> * <ul> * <li>toString()=2002-02-10 11:57:51.804000001</li> * <li>getTimestamp()=1013338671804000001</li> * <li>getMillis()=1013338671804</li> * <li>getMillisOnly()=804</li> * <li>getNanosOnly()=804000001</li> * </ul> * Performance hints (600 MHz Intel PC, Linux 2.4.10, JDK 1.3.1): * <br /> * <ul> * <li>new Timestamp() 1.2 micro seconds</li> * <li>toString() 55 micro seconds the first time, further access 0.1 micro seconds</li> * <li>valueOf() 19 micro seconds</li> * <li>toXml("", false) 16 micro seconds</li> * <li>toXml("", true) 17 micro seconds</li> * </ul> * XML representation: * <pre> * <timestamp nanos='1013346248150000001'> * 2002-02-10 14:04:08.150000001 * </timestamp> * </pre> * or * <pre> * <timestamp nanos='1013346248150000001'/> * </pre> * @author <a href="mailto:xmlBlaster@marcelruff.info">Marcel Ruff</a> * @see org.xmlBlaster.test.classtest.TimestampTest */public class Timestamp implements Comparable, java.io.Serializable{ private static final long serialVersionUID = 1L; public static final int MILLION = 1000000; public static final int BILLION = 1000000000; //private static Object SYNCER = new Object(); private static int nanoCounter = 0; private static long lastMillis = 0L; /** The timestamp in nanoseconds */ private final long timestamp; private transient Long timestampLong; // cached for Long retrieval /** Cache for string representation */ private transient String strFormat = null; /** You may overwrite the tag name for XML dumps in derived classes, defaults to <timestamp ... */ protected String tagName = "timestamp"; /** * Constructs a current timestamp which is guaranteed to be unique in time for this JVM * @exception RuntimeException on overflow (never happens :-=) */ public Timestamp() { synchronized (Timestamp.class) { long timeMillis = System.currentTimeMillis(); if (lastMillis < timeMillis) { nanoCounter = 0; // rewind counter lastMillis = timeMillis; this.timestamp = timeMillis*MILLION; return; } else if (lastMillis == timeMillis) { nanoCounter++; if (nanoCounter >= MILLION) throw new RuntimeException("org.xmlBlaster.util.Timestamp nanoCounter overflow - internal error"); this.timestamp = timeMillis*MILLION + nanoCounter; return; } else { // Time goes backwards - this should not happen // NOTE from ruff 2002/12: This happens on my DELL notebook once and again (jumps to past time with 2-3 msec). // CAUTION: If a sysadmin changes time of the server hardware for say 1 hour backwards // The server should run without day time saving with e.g. GMT nanoCounter++; if (nanoCounter >= MILLION) { throw new RuntimeException("org.xmlBlaster.util.Timestamp nanoCounter overflow - the system time seems to go back into past, giving up after " + MILLION + " times: System.currentTimeMillis() is not ascending old=" + lastMillis + " new=" + timeMillis); } this.timestamp = lastMillis*MILLION + nanoCounter; System.err.println("WARNING: org.xmlBlaster.util.Timestamp System.currentTimeMillis() is not ascending old=" + lastMillis + " new=" + timeMillis + " created timestamp=" + this.timestamp); return; } } } /** * Create a Timestamp with given nanoseconds since 1970 * @see java.util.Date */ public Timestamp(long nanos) { this.timestamp = nanos; } /** * @return The exact timestamp in nanoseconds */ public final long getTimestamp() { return timestamp; } /** * We cache a Long object for reuse (helpful when used as a key in a map). * @return The exact timestamp in nanoseconds */ public final Long getTimestampLong() { if (this.timestampLong == null) { this.timestampLong = new Long(this.timestamp); } return timestampLong; } /** * The nano part only * @return The nano part only */ public final int getNanosOnly() { return (int)(timestamp % BILLION); } /** * The milli part only * @return The milli part only */ public final int getMillisOnly() { return getNanosOnly() / MILLION; } /** * You can use this value for java.util.Date(millis) * @return Rounded to millis * @see #getTime * @see java.util.Date */ public final long getMillis() { return timestamp / MILLION; } /** * You can use this value for java.util.Date(millis) * @return Rounded to millis * @see #getMillis * @see java.util.Date */ public final long getTime() { return getMillis(); } /** * Timestamp in JDBC Timestamp escape format (human readable). * @return The Timestamp in JDBC Timestamp escape format: "2002-02-10 10:52:40.879456789" */ public String toString() { if (strFormat == null) { java.sql.Timestamp ts = new java.sql.Timestamp(getMillis()); //if (ts.getTime() != getMillis()) { // System.out.println("PANIC:java.sql.Timestamp failes: sqlMillis=" + ts.getTime() + " givenMillis=" + getMillis()); //} ts.setNanos(getNanosOnly()); //System.out.println("ts.getTime=" + ts.getTime() + " givenMillis=" + getMillis() + " nanos=" + getNanosOnly()); strFormat = ts.toString(); } return strFormat; } /** * Converts a <code>String</code> object in JDBC timestamp escape format to a * <code>Timestamp</code> value. * * @param s timestamp in format <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> * @return corresponding <code>Timestamp</code> value * @exception java.lang.IllegalArgumentException if the given argument * does not have the format <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> */ public static Timestamp valueOf(String s) { java.sql.Timestamp tsSql = java.sql.Timestamp.valueOf(s); return new Timestamp(((tsSql.getTime()/1000L)*1000L) * MILLION + tsSql.getNanos()); } /** * Compares two Timestamps for ordering. * * @param ts The <code>Timestamp</code> to be compared. * @return the value <code>0</code> if the argument Timestamp is equal to * this Timestamp; a value less than <code>0</code> if this * Timestamp is before the Timestamp argument; and a value greater than * <code>0</code> if this Timestamp is after the Timestamp argument. */ public int compareTo(Object obj) { Timestamp ts = (Timestamp)obj; if (timestamp > ts.getTimestamp()) return 1; else if (timestamp < ts.getTimestamp()) return -1; else return 0; } /** * Tests to see if this <code>Timestamp</code> object is * equal to the given <code>Timestamp</code> object. * * @param stamp the <code>Timestamp</code> value to compare with * @return <code>true</code> if the given <code>Timestamp</code> * object is equal to this <code>Timestamp</code> object; * <code>false</code> otherwise */ public boolean equals(Timestamp ts) { return timestamp == ts.getTimestamp(); } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -