/** | |
* Copyright (c) 2005, 2011, Werner Keil, Ikayzo and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* Werner Keil - initial API and implementation | |
*/ | |
package org.eclipse.uomo.business.types.impl; | |
import static org.eclipse.uomo.business.types.impl.DataHelper.BDT_DELIM; | |
import java.text.SimpleDateFormat; | |
import java.text.ParsePosition; | |
import java.util.Calendar; | |
import java.util.GregorianCalendar; | |
import java.util.TimeZone; | |
import java.sql.Timestamp; | |
import org.eclipse.uomo.business.types.IBasicType; | |
import org.eclipse.uomo.core.UOMoRuntimeException; | |
/** | |
* Timestamp extends java.util.Date, which goes down to the millisecond | |
* | |
* @author <a href="mailto:uomo@catmedia.us">Werner Keil</a> | |
*/ | |
public class TimeStamp extends java.util.Date implements IBasicType { | |
final static long serialVersionUID = 362498820763181265L; | |
/** | |
* TimeStamp constructor - sets a TimeStamp to the current time | |
*/ | |
public TimeStamp() { | |
super((TimeStamp.BuildTimeStamp()).getTime()); | |
} | |
/** | |
* TimeStamp constructor with millisecs (long) | |
*/ | |
public TimeStamp(long m) { | |
super(m); | |
} | |
/** | |
* TimeStamp constructor with String. buildTimeStamp returns a TimeStamp | |
* object, which can't be used directly, so we use getTime | |
* | |
* @throws UOMoRuntimeException | |
*/ | |
public TimeStamp(String s) throws UOMoRuntimeException { | |
super((TimeStamp.BuildTimeStamp(s)).getTime()); | |
} | |
/** | |
* TimeStamp constructor with a java.sql.Timestamp buildTimeStamp returns a | |
* TimeStamp object, which can't be used directly, so we use | |
* getTime | |
* | |
* @throws UOMoRuntimeException | |
*/ | |
public TimeStamp(Timestamp ts) throws UOMoRuntimeException { | |
super((TimeStamp.BuildTimeStamp(ts)).getTime()); | |
} | |
/** | |
* Create a TimeStamp object using current time | |
* | |
* @return TimeStamp | |
*/ | |
static TimeStamp BuildTimeStamp() { | |
Calendar aGregCal = new GregorianCalendar(); | |
java.util.Date date = aGregCal.getTime(); | |
return new TimeStamp(date.getTime()); | |
} | |
/** | |
* Create an (non-Java.util) TimeStamp using a String. This has format | |
* ccyymmddThh:mm:ssttt!zone;calendar;era where zone is an alpha time zone | |
* name known to UOMo; calendar and era are optional. The time from :ss | |
* is also optional. Instead of !zone, you may instead use Ahh:mm, where A | |
* is + or -; in this case, no daylight savings time logic is available. If | |
* adjustment and time zone are both missing, treat as 0, i.e. time is UTC | |
* If an adjustment is present, the sign is as normally used to identify the | |
* time zone - i.e. the offset needed to convert UTC to local time, even | |
* though the first part is local time. This means that, to compute the UTC, | |
* the sign must be reversed - i.e. local time 08:00 am in the EDT zone will | |
* be represented as 08:00-04:00, so that UTC is computed by adding the two | |
* values together. Calendar and era will be ignored for now. | |
* | |
* @return TimeStamp | |
* @param s | |
* java.lang.String | |
* @throws UOMoRuntimeException | |
*/ | |
static TimeStamp BuildTimeStamp(String s) throws UOMoRuntimeException { | |
String str; | |
int sp = s.indexOf(BDT_DELIM); // strip off calendar and/or era | |
if (sp == -1) | |
str = s; | |
else | |
str = s.substring(0, sp); | |
String adj = null; | |
TimeZone tz = null; | |
sp = str.indexOf('!'); | |
if (sp > -1) { | |
String zoneString = str.substring(sp + 1); | |
tz = TimeTz.GetTimeZone(zoneString); | |
if (tz == null) | |
throw new UOMoRuntimeException("Time Zone not found: " | |
+ zoneString); | |
str = str.substring(0, sp); | |
} | |
else { | |
sp = str.indexOf('+'); | |
if (sp == -1) | |
sp = str.indexOf('-'); | |
if (sp > -1) { | |
adj = str.substring(sp); | |
str = str.substring(0, sp); | |
} | |
} | |
if (str.length() < 14) | |
throw new UOMoRuntimeException("Timestamp too short: " + s); | |
if (str.charAt(8) != 'T' || str.charAt(11) != ':') | |
throw new UOMoRuntimeException("Invalid TimeStamp: " + s); | |
String secs = "00000"; | |
if (str.length() > 14) { | |
if (str.charAt(14) != ':') | |
throw new UOMoRuntimeException("Invalid TimeStamp: " + s); | |
if (str.length() != 17 && str.length() != 20) | |
throw new UOMoRuntimeException("Invalid TimeStamp: " + s); | |
secs = str.substring(15) + secs; | |
secs = secs.substring(0, 5); | |
} | |
TimeZone zone = TimeZone.getTimeZone("UTC"); | |
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHH:mmssSSS"); | |
formatter.setTimeZone(zone); | |
String dateString = str.substring(0, 8) + str.substring(9, 14) + secs; | |
ParsePosition pos = new ParsePosition(0); | |
java.util.Date date = formatter.parse(dateString, pos); | |
TimeStamp ts = new TimeStamp(date.getTime()); | |
long millis = 0; | |
if (tz != null) { | |
millis = ts.getTime(); | |
millis -= tz.getRawOffset(); | |
ts.setTime(millis); | |
if (tz.inDaylightTime(ts)) | |
millis -= 3600000; | |
ts.setTime(millis); | |
} | |
if (adj != null) { | |
int hrs; | |
int mins = 0; | |
if (adj.length() == 3) | |
hrs = Integer.parseInt(adj.substring(1)); | |
else { | |
if (adj.charAt(3) != ':' || adj.length() != 6) | |
throw new UOMoRuntimeException( | |
"Invalid TimeStamp adjustment: " + s); | |
hrs = Integer.parseInt(adj.substring(1, 3)); | |
mins = Integer.parseInt(adj.substring(4, 6)); | |
} | |
if (adj.charAt(0) == '+') { | |
hrs = -hrs; | |
mins = -mins; | |
} else if (adj.charAt(0) != '-') | |
throw new UOMoRuntimeException( | |
"Invalid TimeStamp adjustment sign: " + s); | |
millis = ts.getTime(); | |
millis += (3600 * hrs + 60 * mins) * 1000; | |
ts.setTime(millis); | |
} | |
return ts; | |
} | |
/** | |
* Create an TimeStamp using a java.sql.Timestamp. This differs | |
* from an UOMo TimeStamp in that it goes down to the nanosecond. We | |
* will therefore lose fractional milliseconds. | |
* | |
* @return TimeStamp | |
* @param ts | |
* java.sql.Timestamp | |
* @throws UOMoRuntimeException | |
*/ | |
static TimeStamp BuildTimeStamp(java.sql.Timestamp ts) | |
throws UOMoRuntimeException { | |
long millis = ts.getTime(); // gets integral number of seconds | |
millis += ts.getNanos() / 1000000; | |
return new TimeStamp(millis); | |
} | |
/** | |
* Convert this TimeStamp to a java.sql.Timestamp | |
* | |
* @return java.sql.Timestamp | |
*/ | |
public Timestamp convertToSQL() { | |
long millis = getTime() % 1000; | |
java.sql.Timestamp ts = new Timestamp(this.getTime() - millis); | |
ts.setNanos((new Long(millis * 1000000)).intValue()); | |
return ts; | |
} | |
/** | |
* Format a (non-Java.util) TimeStamp object with specified alpha zone or | |
* numeric (+/-) zone | |
* | |
* @return java.lang.String | |
* @throws UOMoRuntimeException | |
*/ | |
public String formatWithZone(String s) throws UOMoRuntimeException { | |
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHH:mm:ssSSS"); | |
TimeZone zone = TimeZone.getTimeZone("UTC"); | |
formatter.setTimeZone(zone); | |
long millis = getTime(); | |
TimeStamp ts = new TimeStamp(millis); | |
String z = s; | |
if (s.charAt(0) == '+' || s.charAt(0) == '-') { | |
int hrs; | |
int mins = 0; | |
if (s.length() == 3) | |
hrs = Integer.parseInt(s.substring(1)); | |
else { | |
if (s.charAt(3) != ':' || s.length() != 6) | |
throw new UOMoRuntimeException( | |
"Invalid TimeStamp adjustment: " + s); | |
hrs = Integer.parseInt(s.substring(1, 3)); | |
mins = Integer.parseInt(s.substring(4, 6)); | |
} | |
if (s.charAt(0) == '-') { | |
hrs = -hrs; | |
mins = -mins; | |
} | |
millis += (hrs * 3600 + mins * 60) * 1000; | |
ts.setTime(millis); | |
} else { | |
TimeZone tz = TimeTz.GetTimeZone(s); | |
if (tz == null) | |
throw new UOMoRuntimeException("Time Zone not found: " + s); | |
millis += tz.getRawOffset(); | |
ts.setTime(millis); | |
if (tz.inDaylightTime(ts)) | |
ts.setTime(millis + 3600000); | |
z = '!' + s; | |
} | |
String str = formatter.format(ts); | |
str = str.substring(0, 8) + 'T' + str.substring(8) + z; | |
return str; | |
} | |
/** | |
* Display a (non-Java.util) TimeStamp object as a 26-byte string | |
* | |
* @return java.lang.String | |
*/ | |
public String serialize() { | |
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHH:mm:ssSSS"); | |
TimeZone zone = TimeZone.getTimeZone("UTC"); | |
formatter.setTimeZone(zone); | |
String str = formatter.format(this); | |
str = str.substring(0, 8) + 'T' + str.substring(8) + "+00:00"; | |
return str; | |
} | |
/** | |
* Create a String from this object | |
* | |
* @return java.lang.String | |
*/ | |
public String toString() { | |
return serialize(); | |
} | |
} |