blob: e4fb893544ff162cc7a71e8d645cb2f17735c3f2 [file] [log] [blame]
/*
* Copyright 2002-2004 The Apache Software Foundation.
*
* 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 org.apache.axis2.databinding.types;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* Class that represents the xsd:time XML Schema type
*/
public class Time implements java.io.Serializable {
private static final long serialVersionUID = -9022201555535589908L;
private Calendar _value;
/**
* a shared java.text.SimpleDateFormat instance used for parsing the basic
* component of the timestamp
*/
private static SimpleDateFormat zulu =
new SimpleDateFormat("HH:mm:ss.SSS'Z'");
// We should always format dates in the GMT timezone
static {
zulu.setTimeZone(TimeZone.getTimeZone("GMT"));
}
/**
* Initializes with a Calender. Year, month and date are ignored.
*/
public Time(Calendar value) {
this._value = value;
_value.set(0,0,0); // ignore year, month, date
}
/**
* Converts a string formatted as HH:mm:ss[.SSS][+/-offset]
*/
public Time(String value) throws NumberFormatException {
_value = makeValue(value);
}
/**
* Returns the time as a calendar. Ignores the year, month and date fields.
* @return Returns calendar value; may be null.
*/
public Calendar getAsCalendar() {
return _value;
}
/**
* Sets the time; ignores year, month, date
* @param date
*/
public void setTime(Calendar date) {
this._value = date;
_value.set(0,0,0); // ignore year, month, date
}
/**
* Sets the time from a date instance.
* @param date
*/
public void setTime(Date date) {
_value.setTime(date);
_value.set(0,0,0); // ignore year, month, date
}
/**
* Utility function that parses xsd:time strings and returns a Date object
*/
private Calendar makeValue(String source) throws NumberFormatException {
Calendar calendar = Calendar.getInstance();
Date date;
validateSource(source);
// convert what we have validated so far
date = ParseHoursMinutesSeconds(source);
int pos = 8; // The "." in hh:mm:ss.sss
// parse optional milliseconds
if ( source != null ) {
if (pos < source.length() && source.charAt(pos)=='.') {
int milliseconds = 0;
int start = ++pos;
while (pos<source.length() &&
Character.isDigit(source.charAt(pos))) {
pos++;
}
String decimal=source.substring(start,pos);
if (decimal.length()==3) {
milliseconds=Integer.parseInt(decimal);
} else if (decimal.length() < 3) {
milliseconds=Integer.parseInt((decimal+"000")
.substring(0,3));
} else {
milliseconds=Integer.parseInt(decimal.substring(0,3));
if (decimal.charAt(3)>='5') {
++milliseconds;
}
}
// add milliseconds to the current date
date.setTime(date.getTime()+milliseconds);
}
// parse optional timezone
if (pos+5 < source.length() &&
(source.charAt(pos)=='+' || (source.charAt(pos)=='-'))) {
if (!Character.isDigit(source.charAt(pos+1)) ||
!Character.isDigit(source.charAt(pos+2)) ||
source.charAt(pos+3) != ':' ||
!Character.isDigit(source.charAt(pos+4)) ||
!Character.isDigit(source.charAt(pos+5)))
{
throw new NumberFormatException();
//Messages.getMessage("badTimezone00"));
}
int hours = (source.charAt(pos+1)-'0')*10
+source.charAt(pos+2)-'0';
int mins = (source.charAt(pos+4)-'0')*10
+source.charAt(pos+5)-'0';
int milliseconds = (hours*60+mins)*60*1000;
// subtract milliseconds from current date to obtain GMT
if (source.charAt(pos)=='+') {
milliseconds=-milliseconds;
}
date.setTime(date.getTime()+milliseconds);
pos+=6;
}
if (pos < source.length() && source.charAt(pos)=='Z') {
pos++;
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
}
if (pos < source.length()) {
throw new NumberFormatException();
//Messages.getMessage("badChars00"));
}
}
calendar.setTime(date);
calendar.set(0,0,0); // ignore year, month, date
return calendar;
}
/**
* Parses the hours, minutes and seconds of a string, by handing it off to
* the java runtime.
* The relevant code returns null if a null string is passed in, so this
* code may return a null date in response.
* @param source
* @return Returns Date.
* @throws NumberFormatException in the event of trouble
*/
private static Date ParseHoursMinutesSeconds(String source) {
Date date;
try {
synchronized (zulu) {
String fulltime = source == null ? null :
(source.substring(0,8)+".000Z");
date = zulu.parse(fulltime);
}
} catch (Exception e) {
throw new NumberFormatException(e.toString());
}
return date;
}
/**
* Validates the source.
* @param source
*/
private void validateSource(String source) {
// validate fixed portion of format
if ( source != null ) {
if (source.charAt(2) != ':' || source.charAt(5) != ':') {
throw new NumberFormatException();
//Messages.getMessage("badTime00"));
}
if (source.length() < 8) {
throw new NumberFormatException();
//Messages.getMessage("badTime00"));
}
}
}
/**
* Returns the time as it would be in GMT. This is accurate to the
* seconds. Milliseconds probably gets lost.
* @return Returns String.
*/
public String toString() {
if(_value==null) {
return "unassigned Time";
}
synchronized (zulu) {
return zulu.format(_value.getTime());
}
}
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof Time)) return false;
Time other = (Time) obj;
if (this == obj) return true;
boolean _equals;
_equals = ((_value == null && other._value == null) ||
(_value != null &&
_value.getTime().equals(other._value.getTime())));
return _equals;
}
/**
* Returns the hashcode of the underlying calendar.
*
* @return Returns an <code>int</code> value.
*/
public int hashCode() {
return _value == null ? 0 : _value.hashCode();
}
}