blob: 08cc976bc15451a1e42ba78b7cd9194968fb6b22 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.axis2.databinding.utils.ConverterUtil;
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;
private boolean isFromString;
private String originalString;
/**
* a shared java.text.SimpleDateFormat instance used for parsing the basic component of the
* timestamp
*/
/** Initializes with a Calender. Year, month and date are ignored. */
public Time(Calendar value) {
this._value = value;
this._value.clear(Calendar.YEAR);
this._value.clear(Calendar.MONTH);
this._value.clear(Calendar.DATE);
}
/** Converts a string formatted as HH:mm:ss[.SSS][+/-offset] */
public Time(String value) throws NumberFormatException {
_value = makeValue(value);
this.isFromString = true;
this.originalString = 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;
this._value.clear(Calendar.YEAR);
this._value.clear(Calendar.MONTH);
this._value.clear(Calendar.DATE);
}
/**
* Sets the time from a date instance.
*
* @param date
*/
public void setTime(Date date) {
_value.setTime(date);
this._value.clear(Calendar.YEAR);
this._value.clear(Calendar.MONTH);
this._value.clear(Calendar.DATE);
}
/** Utility function that parses xsd:time strings and returns a Date object */
private Calendar makeValue(String source) throws NumberFormatException {
// cannonical form of the times is hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
if ((source == null) || (source.trim().length() == 0)){
return null;
}
source = source.trim();
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setLenient(false);
int hour = 0;
int minite = 0;
int second = 0;
long miliSecond = 0;
int timeZoneOffSet = TimeZone.getDefault().getRawOffset();
int milliSecondPartLength = 0;
if (source.length() >= 8) {
if ((source.charAt(2) != ':' )|| (source.charAt(5) != ':')){
throw new RuntimeException("Invalid time format (" + source + ") having : s in wrong places");
}
hour = Integer.parseInt(source.substring(0, 2));
minite = Integer.parseInt(source.substring(3, 5));
second = Integer.parseInt(source.substring(6, 8));
if (source.length() > 8) {
String rest = source.substring(8);
if (rest.startsWith(".")) {
// i.e this have the ('.'s+) part
if (rest.endsWith("Z")) {
// this is in gmt time zone
timeZoneOffSet = 0;
miliSecond = Integer.parseInt(rest.substring(1, rest.lastIndexOf("Z")));
milliSecondPartLength = rest.substring(1,rest.lastIndexOf("Z")).trim().length();
} else if ((rest.lastIndexOf("+") > 0) || (rest.lastIndexOf("-") > 0)) {
// this is given in a general time zione
String timeOffSet = null;
if (rest.lastIndexOf("+") > 0) {
timeOffSet = rest.substring(rest.lastIndexOf("+") + 1);
miliSecond = Integer.parseInt(rest.substring(1, rest.lastIndexOf("+")));
milliSecondPartLength = rest.substring(1, rest.lastIndexOf("+")).trim().length();
// we keep +1 or -1 to finally calculate the value
timeZoneOffSet = 1;
} else if (rest.lastIndexOf("-") > 0) {
timeOffSet = rest.substring(rest.lastIndexOf("-") + 1);
miliSecond = Integer.parseInt(rest.substring(1, rest.lastIndexOf("-")));
milliSecondPartLength = rest.substring(1, rest.lastIndexOf("-")).trim().length();
// we keep +1 or -1 to finally calculate the value
timeZoneOffSet = -1;
}
if (timeOffSet.charAt(2) != ':') {
throw new RuntimeException("invalid time zone format (" + source
+ ") without : at correct place");
}
int hours = Integer.parseInt(timeOffSet.substring(0, 2));
int minits = Integer.parseInt(timeOffSet.substring(3, 5));
timeZoneOffSet = ((hours * 60) + minits) * 60000 * timeZoneOffSet;
} else {
// i.e it does not have time zone
miliSecond = Integer.parseInt(rest.substring(1));
milliSecondPartLength = rest.substring(1).trim().length();
}
} else {
if (rest.startsWith("Z")) {
// this is in gmt time zone
timeZoneOffSet = 0;
} else if (rest.startsWith("+") || rest.startsWith("-")) {
// this is given in a general time zione
if (rest.charAt(3) != ':') {
throw new RuntimeException("invalid time zone format (" + source
+ ") without : at correct place");
}
int hours = Integer.parseInt(rest.substring(1, 3));
int minits = Integer.parseInt(rest.substring(4, 6));
timeZoneOffSet = ((hours * 60) + minits) * 60000;
if (rest.startsWith("-")) {
timeZoneOffSet = timeZoneOffSet * -1;
}
} else {
throw new NumberFormatException("in valid time zone attribute");
}
}
}
} else {
throw new RuntimeException("invalid message string");
}
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minite);
calendar.set(Calendar.SECOND, second);
if (milliSecondPartLength != 3) {
// milisecond part represenst the fraction of the second so we have to
// find the fraction and multiply it by 1000. So if milisecond part
// has three digits nothing required
miliSecond = miliSecond * 1000;
for (int i = 0; i < milliSecondPartLength; i++) {
miliSecond = miliSecond / 10;
}
}
calendar.set(Calendar.MILLISECOND, (int)miliSecond);
calendar.set(Calendar.ZONE_OFFSET, timeZoneOffSet);
calendar.set(Calendar.DST_OFFSET, 0);
return calendar;
}
/**
* 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";
}
if (isFromString) {
return originalString;
} else {
StringBuffer timeString = new StringBuffer();
ConverterUtil.appendTime(_value,timeString);
ConverterUtil.appendTimeZone(_value,timeString);
return timeString.toString();
}
}
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();
}
}