src.com.ibm.as400.access.AS400Time Maven / Gradle / Ivy
Show all versions of jt400-jdk8 Show documentation
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: AS400Time.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 2010-2010 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Hashtable;
import java.util.TimeZone;
/**
Provides a converter between a {@link java.sql.Time java.sql.Time} object and an IBM i time
value such as "23:59:59" or "11:59 PM".
In the IBM i programming reference, this type is referred to as the "Time Data Type",
or DDS data type T.
An IBM i time value simply indicates an hour/minute/second within some (unspecified)
24-hour period, and does not indicate a contextual day, month, year, or time zone.
Internally, this class interprets all date- and time-related strings as relative to the
server's time zone.
Suggestion: To avoid confusion and unexpected results when crossing time zones:
Whenever creating or interpreting instances of {@link java.sql.Date java.sql.Date},
{@link java.sql.Time java.sql.Time}, or {@link java.sql.Timestamp java.sql.Timestamp},
always assume that the reference time zone for the object is the server's time zone, and
avoid using any deprecated methods. If it is necessary to convert date/time values
between the server's time zone and other time zones, use methods of Calendar.
Rather than using toString() to display the value of a date/time object,
use DateFormat.format() after specifying the server timezone.
For example:
import java.text.SimpleDateFormat;
java.sql.Time time1; // value to be generated by AS400Time
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
// Set the formatter's time zone to the server timezone.
formatter.setTimeZone(as400.getTimeZone());
...
System.out.println("Time value: " + formatter.format(time1));
@see AS400Timestamp
@see AS400Date
**/
public class AS400Time extends AS400AbstractTime
{
static final long serialVersionUID = 4L;
private java.sql.Time defaultValue_;
private static Hashtable formatsMap_;
/** The minimum value representable by this date type.
This value represents the time 00:00:00. **/
public static final java.sql.Time MIN_VALUE = new java.sql.Time(0L);
private static final long MILLISECONDS_IN_A_DAY = 24*60*60*1000; // milliseconds in 24 hours
/** The maximum value representable by this date type.
This value represents the time 23:59:59.999.
**/
public static final java.sql.Time MAX_VALUE = new java.sql.Time(MILLISECONDS_IN_A_DAY - 1);
/** Format HMS: hh:mm:ss
Default separator: ':' **/
public static final int FORMAT_HMS = 100; // valid separators: { : . , & }
/** Format ISO: hh.mm.ss
Default separator: '.' **/
public static final int FORMAT_ISO = 101; // valid separators: { . }
/** Format USA: hh:mm AM or hh:mm PM
Default separator: ':'
Note: Unlike the other formats, this format has a granularity of minutes rather than seconds. **/
public static final int FORMAT_USA = 102; // valid separators: { : }
/** Format EUR: hh.mm.ss
Default separator: '.' **/
public static final int FORMAT_EUR = 103; // valid separators: { . }
/** Format JIS: hh:mm:ss
Default separator: ':' **/
public static final int FORMAT_JIS = 104; // valid separators: { : }
// Note to maintenance programmer: Update these values when adding new formats.
private static final int FORMAT_RANGE_MINIMUM = FORMAT_HMS;
private static final int FORMAT_RANGE_MAXIMUM = FORMAT_JIS;
/**
Constructs an AS400Time object. This uses the GMT time zone.
The timezone is used when converting from a string to a "Time" object.
The time object will use the timezone of the current JVM.
Format {@link #FORMAT_ISO FORMAT_ISO} and separator '.' are used.
**/
public AS400Time()
{
// Note: The default internal format for IBM i time variables is *ISO.
this(FORMAT_ISO);
}
/**
Constructs an AS400Time object.
Format {@link #FORMAT_ISO FORMAT_ISO} and separator '.' are used.
* @param timeZone
**/
public AS400Time(TimeZone timeZone)
{
// Note: The default internal format for IBM i time variables is *ISO.
this(timeZone, FORMAT_ISO);
}
/**
Constructs an AS400Time object.
The specified format's default separator is used.
The default GMT timezone is used
@param format The format for this object.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
**/
public AS400Time(int format)
{
super();
setFormat(format, defaultSeparatorFor(format));
}
/**
Constructs an AS400Time object.
The specified format's default separator is used.
* @param timeZone
@param format The format for this object.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
**/
public AS400Time(TimeZone timeZone, int format)
{
super(timeZone);
setFormat(format, defaultSeparatorFor(format));
}
/**
Constructs an AS400Time object.
The specified format's default separator is used.
The default GMT time zone will be used.
@param format The format for this object.
Valid values are:
- {@link #FORMAT_HMS FORMAT_HMS}
- {@link #FORMAT_ISO FORMAT_ISO}
- {@link #FORMAT_USA FORMAT_USA}
- {@link #FORMAT_EUR FORMAT_EUR}
- {@link #FORMAT_JIS FORMAT_JIS}
@param separator The separator character.
Valid values are:
- ' ' (blank)
- ':' (colon)
- '.' (period)
- ',' (comma)
- '&' (ampersand)
- (null)
A null value indicates "no separator".
Refer to the IBM i programming reference to determine which separator characters are valid with each format.
**/
public AS400Time(int format, Character separator)
{
super();
setFormat(format, separator);
}
/**
Constructs an AS400Time object.
The specified format's default separator is used.
* @param timeZone
@param format The format for this object.
Valid values are:
- {@link #FORMAT_HMS FORMAT_HMS}
- {@link #FORMAT_ISO FORMAT_ISO}
- {@link #FORMAT_USA FORMAT_USA}
- {@link #FORMAT_EUR FORMAT_EUR}
- {@link #FORMAT_JIS FORMAT_JIS}
@param separator The separator character.
Valid values are:
- ' ' (blank)
- ':' (colon)
- '.' (period)
- ',' (comma)
- '&' (ampersand)
- (null)
A null value indicates "no separator".
Refer to the IBM i programming reference to determine which separator characters are valid with each format.
**/
public AS400Time(TimeZone timeZone, int format, Character separator)
{
super(timeZone);
setFormat(format, separator);
}
// Overrides non-public method of superclass, making it public.
/**
Gets the format of this AS400Time object.
@return format The format for this object.
For a list of possible values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
**/
public int getFormat()
{
return super.getFormat();
}
/**
Gets the separator character of this AS400Time object.
@return separator The separator character.
For a list of possible values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
If the format contains no separators, null is returned.
@see #setFormat(int,Character)
**/
public Character getSeparator()
{
return super.getSeparator();
}
/**
Sets the format of this AS400Time object.
The specified format's default separator is used.
@param format The format for this object.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
**/
public void setFormat(int format)
{
super.setFormat(format, defaultSeparatorFor(format));
}
// Method used by TimeFieldDescription.
/**
Sets the format of this AS400Time object.
The specified format's default separator character is used.
@param format The format for this object, expressed as a string.
For a list of valid values, refer to {@link #toFormat(String) toFormat(String)}.
**/
void setFormat(String format)
{
super.setFormat(toFormat(format));
}
// Method used by TimeFieldDescription.
/**
Sets the separator character of this AS400Time object.
@param separator The separator character.
**/
void setSeparator(Character separator)
{
super.setSeparator(separator);
}
// Overrides non-public method of superclass, making it public.
/**
Sets the format of this AS400Time object.
@param format The format for this object.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
@param separator The separator character.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
A null value indicates "no separator".
Refer to the IBM i programming reference to determine which separator characters are valid with each format.
**/
public void setFormat(int format, Character separator)
{
super.setFormat(format, separator);
}
/**
Sets the format of this AS400Time object.
@param format The format for this object.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
@param separator The separator character.
@deprecated Use {@link #setFormat(int,Character) setFormat(int,Character)} instead.
**/
public void setFormat(int format, char separator)
{
super.setFormat(format, new Character(separator));
}
private static Hashtable getFormatsMap()
{
if (formatsMap_ == null)
{
synchronized (AS400Time.class)
{
if (formatsMap_ == null)
{
formatsMap_ = new Hashtable(12);
formatsMap_.put("HMS", new Integer(FORMAT_HMS));
formatsMap_.put("ISO", new Integer(FORMAT_ISO));
formatsMap_.put("USA", new Integer(FORMAT_USA));
formatsMap_.put("EUR", new Integer(FORMAT_EUR));
formatsMap_.put("JIS", new Integer(FORMAT_JIS));
}
}
}
return formatsMap_;
}
/**
Returns the integer format value that corresponds to specified format name.
If null is specified, the default format (FORMAT_ISO) is returned.
This method is provided for use by the PCML infrastructure.
@param formatName The format name.
Valid values are:
- HMS
- ISO
- USA
- EUR
- JIS
@return the format value. For example, if formatName is "ISO", then {@link #FORMAT_ISO FORMAT_ISO} is returned.
**/
public static int toFormat(String formatName)
{
if (formatName == null || formatName.length() == 0) {
if (Trace.traceOn_) {
Trace.log(Trace.DIAGNOSTIC, "AS400Time.toFormat("+formatName+"): Returning default time format.");
}
return FORMAT_ISO;
}
Integer formatInt = (Integer)getFormatsMap().get(formatName.trim().toUpperCase());
if (formatInt == null) {
throw new ExtendedIllegalArgumentException("format ("+formatName+")", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
}
return formatInt.intValue();
}
// Overrides method of superclass.
/**
Returns a Java object representing the default value of the data type.
@return A {@link java.sql.Time java.sql.Time} object representing time 00:00:00 GMT (on January 1, 1970).
**/
public Object getDefaultValue()
{
if (defaultValue_ == null) {
defaultValue_ = new java.sql.Time(0L); // 00:00:00 GMT
}
return defaultValue_;
}
// Implements abstract method of superclass.
/**
Returns {@link AS400DataType#TYPE_TIME TYPE_TIME}.
@return AS400DataType.TYPE_TIME.
**/
public int getInstanceType()
{
return AS400DataType.TYPE_TIME;
}
// Implements abstract method of superclass.
/**
Returns the Java class that corresponds with this data type.
@return java.sql.Time.class.
**/
public Class getJavaType()
{
return java.sql.Time.class;
}
// Overrides method of superclass. This allows us to be more specific in the javadoc.
/**
Converts the specified Java object into IBM i format in the specified byte array.
@param javaValue The object corresponding to the data type. It must be an instance of {@link java.sql.Time java.sql.Time}.
The range of valid values is {@link #MIN_VALUE MIN_VALUE} through {@link #MAX_VALUE MAX_VALUE}.
Year, month, day-of-month, and fractional seconds are disregarded.
@param as400Value The array to receive the data type in IBM i format. There must be enough space to hold the IBM i value.
@param offset The offset into the byte array for the start of the IBM i value. It must be greater than or equal to zero.
@return Eight (8), the number of bytes in the IBM i representation of the data type.
**/
public int toBytes(Object javaValue, byte[] as400Value, int offset)
{
return super.toBytes(javaValue, as400Value, offset);
}
// Implements abstract method of superclass.
/**
Converts the specified IBM i data type to a Java object.
@param as400Value The array containing the data type in IBM i format. The entire data type must be represented.
@param offset The offset into the byte array for the start of the IBM i value. It must be greater than or equal to zero.
@return a {@link java.sql.Time java.sql.Time} object, representing the number of milliseconds into the day.
The reference time zone for the object is the timezone specified on the constructor.
**/
public Object toObject(byte[] as400Value, int offset)
{
if (as400Value == null) throw new NullPointerException("as400Value");
String timeString = getCharConverter().byteArrayToString(as400Value, offset, getLength());
// Parse the string, and create a java.sql.Time object.
return parse(timeString);
}
// Implements abstract method of superclass.
/**
Converts the specified Java object into a String representation that is consistent with the format of this data type.
@param javaValue The object corresponding to the data type. This must be an instance of {@link java.sql.Time java.sql.Time},
and must be within the range representable by this data type. Any timezone context is disregarded.
@return A String representation of the specified value, formatted appropriately for this data type.
**/
public String toString(Object javaValue)
{
if (javaValue == null) throw new NullPointerException("javaValue");
java.sql.Time timeObj;
try { timeObj = (java.sql.Time)javaValue; }
catch (ClassCastException e) {
Trace.log(Trace.ERROR, "javaValue is of type " + javaValue.getClass().getName());
throw e;
}
return getDateFormatter().format(timeObj);
}
/**
Converts a string representation of a time, to a Java object.
@param source A time value expressed as a string in the format specified for this AS400Time object.
@return A {@link java.sql.Time java.sql.Time} object representing the specified time.
The reference timezone is the timezone specified for the object.
**/
public java.sql.Time parse(String source)
{
if (source == null) throw new NullPointerException("source");
try
{
SimpleDateFormat formatter = getDateFormatter();
java.util.Date dateObj = formatter.parse(source);
long milliseconds = dateObj.getTime();
java.sql.Time time = new java.sql.Time(milliseconds); // argument is "milliseconds into day"
// Convert to the base time type.
return time;
}
catch (Exception e) {
// Assume that the exception is because we got bad input.
Trace.log(Trace.ERROR, e.getMessage(), source);
Trace.log(Trace.ERROR, "Time string is expected to be in format: " + patternFor(getFormat(), getSeparator()));
throw new ExtendedIllegalArgumentException("source ("+source+")", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
}
}
/**
Converts the specified HMS representation of a time, to a Java object.
This method is provided for use by the PCML infrastructure;
in particular, when parsing 'init=' values for 'time' data elements.
This method assumes that the reference timezone is GMT
@param source A time value expressed as a string in format HH:mm:ss.
@return A {@link java.sql.Time java.sql.Time} object representing the specified time.
**/
public static java.sql.Time parseXsdString(String source)
{
return parseXsdString(source, AS400AbstractTime.TIMEZONE_GMT);
}
/**
Converts the specified HMS representation of a time, to a Java object.
This method is provided for use by the PCML infrastructure;
in particular, when parsing 'init=' values for 'time' data elements.
@param source A time value expressed as a string in format HH:mm:ss.
@param timeZone The time zone used to interpret the value.
@return A {@link java.sql.Time java.sql.Time} object representing the specified time.
**/
public static java.sql.Time parseXsdString(String source, TimeZone timeZone)
{
if (source == null) throw new NullPointerException("source");
try
{
java.util.Date simpleDateObj = getTimeFormatterXSD(timeZone).parse(source);
long milliseconds = simpleDateObj.getTime();
java.sql.Time returnTime = new java.sql.Time(milliseconds);
return returnTime;
}
catch (ParseException e) {
// Assume that the exception is because we got bad input.
Trace.log(Trace.ERROR, e.getMessage(), source);
Trace.log(Trace.ERROR, "Value is expected to be in standard XML Schema 'time' format: " + TIME_PATTERN_XSD);
throw new ExtendedIllegalArgumentException("source ("+source+")", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
}
}
/**
Converts the specified Java object into a String representation that is consistent with the format of this data type.
This method is provided for use by the PCML infrastructure.
This version uses the GMT timezone.
@param javaValue The object corresponding to the data type. This must be an instance of {@link java.sql.Time java.sql.Time}, and must be within the range specifiable by this data type.
@return The time expressed as a string in format HH:mm:ss.
**/
public static String toXsdString(Object javaValue)
{
return toXsdString(javaValue, TIMEZONE_GMT );
}
/**
Converts the specified Java object into a String representation that is consistent with the format of this data type.
This method is provided for use by the PCML infrastructure.
@param javaValue The object corresponding to the data type. This must be an instance of
{@link java.sql.Time java.sql.Time}, and must be within the range specifiable by this data type.
@param timeZone The time zone used to interpret the value.
@return The time expressed as a string in format HH:mm:ss.
**/
public static String toXsdString(Object javaValue, TimeZone timeZone)
{
if (javaValue == null) throw new NullPointerException("javaValue");
java.sql.Time timeObj;
try { timeObj = (java.sql.Time)javaValue; }
catch (ClassCastException e) {
Trace.log(Trace.ERROR, "javaValue is of type " + javaValue.getClass().getName());
throw e;
}
return getTimeFormatterXSD(timeZone).format(timeObj);
}
// Implements abstract method of superclass.
String patternFor(int format, Character separator)
{
String sep = ( separator == null ? "" : separator.toString());
switch (format)
{
case FORMAT_USA:
String sep2 = ( sep.equals("") ? "" : " " );
return "hh" + sep + "mm" + sep2 + "a"; // hh:mm AM hh:mm PM
default:
return "HH" + sep + "mm" + sep + "ss";
}
}
// Implements abstract method of superclass.
Character defaultSeparatorFor(int format)
{
if (!isValidFormat(format)) {
throw new ExtendedIllegalArgumentException("format ("+format+")", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
}
switch (format)
{
case FORMAT_HMS:
case FORMAT_USA:
case FORMAT_JIS:
return COLON; // ':'
case FORMAT_ISO:
case FORMAT_EUR:
return PERIOD; // '.'
default: // none of the above formats
// Should never happen.
throw new InternalErrorException(InternalErrorException.UNKNOWN, "Unrecognized format: " + format, null);
}
}
// Implements abstract method of superclass.
boolean isValidFormat(int format)
{
return validateFormat(format);
}
/**
Validates the specified format value.
This method is provided for use by the PCML infrastructure.
@param format The format.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
@return true if the format is valid; false otherwise.
**/
public static boolean validateFormat(int format)
{
if (format < FORMAT_RANGE_MINIMUM || format > FORMAT_RANGE_MAXIMUM) return false;
else return true;
}
/**
Returns the number of bytes occupied on the IBM i system by a field of this type.
This method is provided for use by the PCML infrastructure.
@param format The format. This argument is ignored.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
@param separator The separator character. This argument is ignored.
For a list of valid values, refer to {@link #AS400Time(int,Character) AS400Time(int,Character)}.
@return the number of bytes occupied.
**/
public static int getByteLength(int format, Character separator)
{
if (separator == null) return 6; // field size (without separators) is 6 bytes
else return 8; // field size (with separators) is 8 bytes
}
// Implements abstract method of superclass.
int lengthFor(int format)
{
return getByteLength(format, getSeparator());
}
}