You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2008/08/18 13:26:52 UTC
svn commit: r686726 - in /directory/shared/branches/bigbang/ldap/src:
main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java
test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java
Author: seelmann
Date: Mon Aug 18 04:26:51 2008
New Revision: 686726
URL: http://svn.apache.org/viewvc?rev=686726&view=rev
Log:
Fix for DIRSHARED-19: Added GeneralizedTime class plus tests
Added:
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java
Added: directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java?rev=686726&view=auto
==============================================================================
--- directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java (added)
+++ directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java Mon Aug 18 04:26:51 2008
@@ -0,0 +1,749 @@
+/*
+ * 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.directory.shared.ldap.util;
+
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+
+/**
+ * <p>This class represents the generalized time syntax as defined in
+ * RFC 4517 section 3.3.13.</p>
+ *
+ * <p>The date, time and time zone information is internally backed
+ * by an {@link java.util.Calendar} object</p>
+ *
+ * <p>Leap seconds are not supported, as {@link java.util.Calendar}
+ * does not support leap seconds.</p>
+ *
+ * <pre>
+ * 3.3.13. Generalized Time
+ *
+ * A value of the Generalized Time syntax is a character string
+ * representing a date and time. The LDAP-specific encoding of a value
+ * of this syntax is a restriction of the format defined in [ISO8601],
+ * and is described by the following ABNF:
+ *
+ * GeneralizedTime = century year month day hour
+ * [ minute [ second / leap-second ] ]
+ * [ fraction ]
+ * g-time-zone
+ *
+ * century = 2(%x30-39) ; "00" to "99"
+ * year = 2(%x30-39) ; "00" to "99"
+ * month = ( %x30 %x31-39 ) ; "01" (January) to "09"
+ * / ( %x31 %x30-32 ) ; "10" to "12"
+ * day = ( %x30 %x31-39 ) ; "01" to "09"
+ * / ( %x31-32 %x30-39 ) ; "10" to "29"
+ * / ( %x33 %x30-31 ) ; "30" to "31"
+ * hour = ( %x30-31 %x30-39 ) / ( %x32 %x30-33 ) ; "00" to "23"
+ * minute = %x30-35 %x30-39 ; "00" to "59"
+ *
+ * second = ( %x30-35 %x30-39 ) ; "00" to "59"
+ * leap-second = ( %x36 %x30 ) ; "60"
+ *
+ * fraction = ( DOT / COMMA ) 1*(%x30-39)
+ * g-time-zone = %x5A ; "Z"
+ * / g-differential
+ * g-differential = ( MINUS / PLUS ) hour [ minute ]
+ * MINUS = %x2D ; minus sign ("-")
+ *
+ * The <DOT>, <COMMA>, and <PLUS> rules are defined in [RFC4512].
+ *
+ * The above ABNF allows character strings that do not represent valid
+ * dates (in the Gregorian calendar) and/or valid times (e.g., February
+ * 31, 1994). Such character strings SHOULD be considered invalid for
+ * this syntax.
+ *
+ * The time value represents coordinated universal time (equivalent to
+ * Greenwich Mean Time) if the "Z" form of <g-time-zone> is used;
+ * otherwise, the value represents a local time in the time zone
+ * indicated by <g-differential>. In the latter case, coordinated
+ * universal time can be calculated by subtracting the differential from
+ * the local time. The "Z" form of <g-time-zone> SHOULD be used in
+ * preference to <g-differential>.
+ *
+ * If <minute> is omitted, then <fraction> represents a fraction of an
+ * hour; otherwise, if <second> and <leap-second> are omitted, then
+ * <fraction> represents a fraction of a minute; otherwise, <fraction>
+ * represents a fraction of a second.
+ *
+ * Examples:
+ * 199412161032Z
+ * 199412160532-0500
+ *
+ * Both example values represent the same coordinated universal time:
+ * 10:32 AM, December 16, 1994.
+ *
+ * The LDAP definition for the Generalized Time syntax is:
+ *
+ * ( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )
+ *
+ * This syntax corresponds to the GeneralizedTime ASN.1 type from
+ * [ASN.1], with the constraint that local time without a differential
+ * SHALL NOT be used.
+ *
+ * </pre>
+ */
+public class GeneralizedTime implements Comparable<GeneralizedTime>
+{
+
+ public enum Format
+ {
+ YEAR_MONTH_DAY_HOUR_MIN_SEC, YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION,
+
+ YEAR_MONTH_DAY_HOUR_MIN, YEAR_MONTH_DAY_HOUR_MIN_FRACTION,
+
+ YEAR_MONTH_DAY_HOUR, YEAR_MONTH_DAY_HOUR_FRACTION, ;
+ }
+
+ public enum FractionDelimiter
+ {
+ DOT, COMMA
+ }
+
+ public enum TimeZoneFormat
+ {
+ Z, DIFF_HOUR, DIFF_HOUR_MINUTE;
+ }
+
+ private static final TimeZone GMT = TimeZone.getTimeZone( "GMT" );
+
+ /** The user provided value */
+ private String upGeneralizedTime;
+
+ /** The user provided format */
+ private Format upFormat;
+
+ /** The user provided time zone format */
+ private TimeZoneFormat upTimeZoneFormat;
+
+ /** The user provided fraction delimiter */
+ private FractionDelimiter upFractionDelimiter;
+
+ /** the user provided fraction length */
+ private int upFractionLength;
+
+ /** The calendar */
+ private Calendar calendar;
+
+
+ /**
+ * Creates a new instance of GeneralizedTime, based on the given Calendar object.
+ * Uses <pre>Format.YEAR_MONTH_DAY_HOUR_MIN_SEC</pre> as default format and
+ * <pre>TimeZoneFormat.Z</pre> as default time zone format.
+ *
+ * @param calendar the calendar containing the date, time and timezone information
+ */
+ public GeneralizedTime( Calendar calendar )
+ {
+ if ( calendar == null )
+ {
+ throw new IllegalArgumentException( "Calendar must not be null." );
+ }
+
+ this.calendar = calendar;
+ upGeneralizedTime = null;
+ upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC;
+ upTimeZoneFormat = TimeZoneFormat.Z;
+ upFractionDelimiter = FractionDelimiter.DOT;
+ upFractionLength = 3;
+ }
+
+
+ /**
+ * Creates a new instance of GeneralizedTime, based on the
+ * given generalized time string.
+ *
+ * @param generalizedTime the generalized time
+ *
+ * @throws ParseException if the given generalized time can't be parsed.
+ */
+ public GeneralizedTime( String generalizedTime ) throws ParseException
+ {
+ if ( generalizedTime == null )
+ {
+ throw new ParseException( "generalizedTime is null", 0 );
+ }
+
+ this.upGeneralizedTime = generalizedTime;
+
+ calendar = Calendar.getInstance();
+ calendar.setTimeInMillis( 0 );
+ calendar.setLenient( false );
+
+ parseYear();
+ parseMonth();
+ parseDay();
+ parseHour();
+
+ if ( upGeneralizedTime.length() < 11 )
+ {
+ throw new ParseException(
+ "Generalized Time too short, doesn't contain field 'minute' or 'fraction of hour' or 'timezone'.", 10 );
+ }
+
+ // pos 10:
+ // if digit => minute field
+ // if . or , => fraction of hour field
+ // if Z or + or - => timezone field
+ // else error
+ int pos = 10;
+ char c = upGeneralizedTime.charAt( pos );
+ if ( '0' <= c && c <= '9' )
+ {
+ parseMinute();
+
+ if ( upGeneralizedTime.length() < 13 )
+ {
+ throw new ParseException(
+ "Generalized Time too short, doesn't contain field 'second' or 'fraction of minute' or 'timezone'.",
+ 12 );
+ }
+
+ // pos 12:
+ // if digit => second field
+ // if . or , => fraction of minute field
+ // if Z or + or - => timezone field
+ // else error
+ pos = 12;
+ c = upGeneralizedTime.charAt( pos );
+ if ( '0' <= c && c <= '9' )
+ {
+ parseSecond();
+
+ if ( upGeneralizedTime.length() < 15 )
+ {
+ throw new ParseException(
+ "Generalized Time too short, doesn't contain field 'fraction of second' or 'timezone'.", 14 );
+ }
+
+ // pos 14:
+ // if . or , => fraction of second field
+ // if Z or + or - => timezone field
+ // else error
+ pos = 14;
+ c = upGeneralizedTime.charAt( pos );
+ if ( c == '.' || c == ',' )
+ {
+ // read fraction of second
+ parseFractionOfSecond();
+ pos += 1 + upFractionLength;
+
+ parseTimezone( pos );
+ upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION;
+ }
+ else if ( c == 'Z' || c == '+' || c == '-' )
+ {
+ // read timezone
+ parseTimezone( pos );
+ upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC;
+ }
+ else
+ {
+ throw new ParseException(
+ "Invalid Time too short, expected field 'fraction of second' or 'timezone'.", 14 );
+ }
+ }
+ else if ( c == '.' || c == ',' )
+ {
+ // read fraction of minute
+ parseFractionOfMinute();
+ pos += 1 + upFractionLength;
+
+ parseTimezone( pos );
+ upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_FRACTION;
+ }
+ else if ( c == 'Z' || c == '+' || c == '-' )
+ {
+ // read timezone
+ parseTimezone( pos );
+ upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN;
+ }
+ else
+ {
+ throw new ParseException(
+ "Invalid Time too short, expected field 'second' or 'fraction of minute' or 'timezone'.", 12 );
+ }
+ }
+ else if ( c == '.' || c == ',' )
+ {
+ // read fraction of hour
+ parseFractionOfHour();
+ pos += 1 + upFractionLength;
+
+ parseTimezone( pos );
+ upFormat = Format.YEAR_MONTH_DAY_HOUR_FRACTION;
+ }
+ else if ( c == 'Z' || c == '+' || c == '-' )
+ {
+ // read timezone
+ parseTimezone( pos );
+ upFormat = Format.YEAR_MONTH_DAY_HOUR;
+ }
+ else
+ {
+ throw new ParseException(
+ "Invalid Generalized Time, expected field 'minute' or 'fraction of hour' or 'timezone'.", 10 );
+ }
+
+ // this calculates and verifies the calendar
+ try
+ {
+ calendar.getTimeInMillis();
+ }
+ catch ( IllegalArgumentException iae )
+ {
+ throw new ParseException( "Invalid date/time values.", 0 );
+ }
+ }
+
+
+ private void parseTimezone( int pos ) throws ParseException
+ {
+ if ( upGeneralizedTime.length() < pos + 1 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'timezone'.", pos );
+ }
+
+ char c = upGeneralizedTime.charAt( pos );
+ if ( c == 'Z' )
+ {
+ calendar.setTimeZone( GMT );
+ upTimeZoneFormat = TimeZoneFormat.Z;
+
+ if ( upGeneralizedTime.length() > pos + 1 )
+ {
+ throw new ParseException( "Invalid Generalized Time, expected 'timezone' as the last field.", pos + 1 );
+ }
+ }
+ else if ( c == '+' || c == '-' )
+ {
+ StringBuilder sb = new StringBuilder( "GMT" );
+ sb.append( c );
+
+ String digits = getAllDigits( pos + 1 );
+ sb.append( digits );
+
+ if ( digits.length() == 2 && digits.matches( "^([01]\\d|2[0-3])$" ) )
+ {
+ TimeZone timeZone = TimeZone.getTimeZone( sb.toString() );
+ calendar.setTimeZone( timeZone );
+ upTimeZoneFormat = TimeZoneFormat.DIFF_HOUR;
+ }
+ else if ( digits.length() == 4 && digits.matches( "^([01]\\d|2[0-3])([0-5]\\d)$" ) )
+ {
+ TimeZone timeZone = TimeZone.getTimeZone( sb.toString() );
+ calendar.setTimeZone( timeZone );
+ upTimeZoneFormat = TimeZoneFormat.DIFF_HOUR_MINUTE;
+ }
+ else
+ {
+ throw new ParseException(
+ "Invalid Generalized Time, expected field 'timezone' must contain 2 or 4 digits.", pos );
+ }
+
+ if ( upGeneralizedTime.length() > pos + 1 + digits.length() )
+ {
+ throw new ParseException( "Invalid Generalized Time, expected 'timezone' as the last field.", pos + 1
+ + digits.length() );
+ }
+ }
+ }
+
+
+ private void parseFractionOfSecond() throws ParseException
+ {
+ parseFractionDelmiter( 14 );
+ String fraction = getFraction( 14 + 1 );
+ upFractionLength = fraction.length();
+
+ double fract = Double.parseDouble( "0." + fraction );
+ int millisecond = ( int ) Math.round( fract * 1000 );
+
+ calendar.set( Calendar.MILLISECOND, millisecond );
+ }
+
+
+ private void parseFractionOfMinute() throws ParseException
+ {
+ parseFractionDelmiter( 12 );
+ String fraction = getFraction( 12 + 1 );
+ upFractionLength = fraction.length();
+
+ double fract = Double.parseDouble( "0." + fraction );
+ int milliseconds = ( int ) Math.round( fract * 1000 * 60 );
+ int second = milliseconds / 1000;
+ int millisecond = milliseconds - ( second * 1000 );
+
+ calendar.set( Calendar.SECOND, second );
+ calendar.set( Calendar.MILLISECOND, millisecond );
+ }
+
+
+ private void parseFractionOfHour() throws ParseException
+ {
+ parseFractionDelmiter( 10 );
+ String fraction = getFraction( 10 + 1 );
+ upFractionLength = fraction.length();
+
+ double fract = Double.parseDouble( "0." + fraction );
+ int milliseconds = ( int ) Math.round( fract * 1000 * 60 * 60 );
+ int minute = milliseconds / ( 1000 * 60 );
+ int second = ( milliseconds - ( minute * 60 * 1000 ) ) / 1000;
+ int millisecond = milliseconds - ( minute * 60 * 1000 ) - ( second * 1000 );
+
+ calendar.set( Calendar.MINUTE, minute );
+ calendar.set( Calendar.SECOND, second );
+ calendar.set( Calendar.MILLISECOND, millisecond );
+ }
+
+
+ private void parseFractionDelmiter( int fractionDelimiterPos )
+ {
+ char c = upGeneralizedTime.charAt( fractionDelimiterPos );
+ upFractionDelimiter = c == '.' ? FractionDelimiter.DOT : FractionDelimiter.COMMA;
+ }
+
+
+ private String getFraction( int startIndex ) throws ParseException
+ {
+ String fraction = getAllDigits( startIndex );
+
+ // minimum one digit
+ if ( fraction.length() == 0 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain number for 'fraction'.", startIndex );
+ }
+
+ return fraction;
+ }
+
+
+ private String getAllDigits( int startIndex )
+ {
+ StringBuilder sb = new StringBuilder();
+ while ( upGeneralizedTime.length() > startIndex )
+ {
+ char c = upGeneralizedTime.charAt( startIndex );
+ if ( '0' <= c && c <= '9' )
+ {
+ sb.append( c );
+ startIndex++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+
+ private void parseSecond() throws ParseException
+ {
+ // read minute
+ if ( upGeneralizedTime.length() < 14 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'second'.", 12 );
+ }
+ try
+ {
+ int second = Integer.parseInt( upGeneralizedTime.substring( 12, 14 ) );
+ calendar.set( Calendar.SECOND, second );
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new ParseException( "Invalid Generalized Time, field 'second' is not numeric.", 12 );
+ }
+ }
+
+
+ private void parseMinute() throws ParseException
+ {
+ // read minute
+ if ( upGeneralizedTime.length() < 12 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'minute'.", 10 );
+ }
+ try
+ {
+ int minute = Integer.parseInt( upGeneralizedTime.substring( 10, 12 ) );
+ calendar.set( Calendar.MINUTE, minute );
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new ParseException( "Invalid Generalized Time, field 'minute' is not numeric.", 10 );
+ }
+ }
+
+
+ private void parseHour() throws ParseException
+ {
+ if ( upGeneralizedTime.length() < 10 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'hour'.", 8 );
+ }
+ try
+ {
+ int hour = Integer.parseInt( upGeneralizedTime.substring( 8, 10 ) );
+ calendar.set( Calendar.HOUR_OF_DAY, hour );
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new ParseException( "Invalid Generalized Time, field 'hour' is not numeric.", 8 );
+ }
+ }
+
+
+ private void parseDay() throws ParseException
+ {
+ if ( upGeneralizedTime.length() < 8 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'day'.", 6 );
+ }
+ try
+ {
+ int day = Integer.parseInt( upGeneralizedTime.substring( 6, 8 ) );
+ calendar.set( Calendar.DAY_OF_MONTH, day );
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new ParseException( "Invalid Generalized Time, field 'day' is not numeric.", 6 );
+ }
+ }
+
+
+ private void parseMonth() throws ParseException
+ {
+ if ( upGeneralizedTime.length() < 6 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'month'.", 4 );
+ }
+ try
+ {
+ int month = Integer.parseInt( upGeneralizedTime.substring( 4, 6 ) );
+ calendar.set( Calendar.MONTH, month - 1 );
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new ParseException( "Invalid Generalized Time, field 'month' is not numeric.", 4 );
+ }
+ }
+
+
+ private void parseYear() throws ParseException
+ {
+ if ( upGeneralizedTime.length() < 4 )
+ {
+ throw new ParseException( "Generalized Time too short, doesn't contain field 'century/year'.", 0 );
+ }
+ try
+ {
+ int year = Integer.parseInt( upGeneralizedTime.substring( 0, 4 ) );
+ calendar.set( Calendar.YEAR, year );
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new ParseException( "Invalid Generalized Time, field 'century/year' is not numeric.", 0 );
+ }
+ }
+
+
+ /**
+ * Returns the string representation of this generalized time.
+ * This method uses the same format as the user provided format.
+ *
+ * @return the string representation of this generalized time
+ */
+ public String toGeneralizedTime()
+ {
+ return toGeneralizedTime( upFormat, upFractionDelimiter, upFractionLength, upTimeZoneFormat );
+ }
+
+
+ /**
+ * Returns the string representation of this generalized time.
+ *
+ * @param format the target format
+ * @param fractionDelimiter the target fraction delimiter, may be null
+ * @param fractionLenth the fraction length
+ * @param timeZoneFormat the target time zone format
+ *
+ * @return the string
+ */
+ public String toGeneralizedTime( Format format, FractionDelimiter fractionDelimiter, int fractionLength,
+ TimeZoneFormat timeZoneFormat )
+ {
+ NumberFormat twoDigits = new DecimalFormat( "00" );
+ NumberFormat fourDigits = new DecimalFormat( "00" );
+ String fractionFormat = "";
+ for ( int i = 0; i < fractionLength && i < 3; i++ )
+ {
+ fractionFormat += "0";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append( fourDigits.format( calendar.get( Calendar.YEAR ) ) );
+ sb.append( twoDigits.format( calendar.get( Calendar.MONTH ) + 1 ) );
+ sb.append( twoDigits.format( calendar.get( Calendar.DAY_OF_MONTH ) ) );
+ sb.append( twoDigits.format( calendar.get( Calendar.HOUR_OF_DAY ) ) );
+
+ switch ( format )
+ {
+ case YEAR_MONTH_DAY_HOUR_MIN_SEC:
+ sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+ sb.append( twoDigits.format( calendar.get( Calendar.SECOND ) ) );
+ break;
+
+ case YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION:
+ sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+ sb.append( twoDigits.format( calendar.get( Calendar.SECOND ) ) );
+
+ NumberFormat fractionDigits = new DecimalFormat( fractionFormat );
+ sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
+ sb.append( fractionDigits.format( calendar.get( Calendar.MILLISECOND ) ) );
+ break;
+
+ case YEAR_MONTH_DAY_HOUR_MIN:
+ sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+ break;
+
+ case YEAR_MONTH_DAY_HOUR_MIN_FRACTION:
+ sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+
+ // sec + millis => fraction of minute
+ double millisec = 1000 * calendar.get( Calendar.SECOND ) + calendar.get( Calendar.MILLISECOND );
+ double fraction = millisec / ( 1000 * 60 );
+ fractionDigits = new DecimalFormat( "0." + fractionFormat );
+ sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
+ sb.append( fractionDigits.format( fraction ).substring( 2 ) );
+ break;
+
+ case YEAR_MONTH_DAY_HOUR_FRACTION:
+ // min + sec + millis => fraction of minute
+ millisec = 1000 * 60 * calendar.get( Calendar.MINUTE ) + 1000 * calendar.get( Calendar.SECOND )
+ + calendar.get( Calendar.MILLISECOND );
+ fraction = millisec / ( 1000 * 60 * 60 );
+ fractionDigits = new DecimalFormat( "0." + fractionFormat );
+ sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
+ sb.append( fractionDigits.format( fraction ).substring( 2 ) );
+
+ break;
+ }
+
+ if ( timeZoneFormat == TimeZoneFormat.Z && calendar.getTimeZone().hasSameRules( GMT ) )
+ {
+ sb.append( 'Z' );
+ }
+ else
+ {
+ TimeZone timeZone = calendar.getTimeZone();
+ int rawOffset = timeZone.getRawOffset();
+ sb.append( rawOffset < 0 ? '-' : '+' );
+
+ rawOffset = Math.abs( rawOffset );
+ int hour = rawOffset / ( 60 * 60 * 1000 );
+ int minute = ( rawOffset - ( hour * 60 * 60 * 1000 ) ) / ( 1000 * 60 );
+
+ if ( hour < 10 )
+ {
+ sb.append( '0' );
+ }
+ sb.append( hour );
+
+ if ( timeZoneFormat == TimeZoneFormat.DIFF_HOUR_MINUTE || timeZoneFormat == TimeZoneFormat.Z )
+ {
+ if ( hour < 10 )
+ {
+ sb.append( '0' );
+ }
+ sb.append( minute );
+ }
+ }
+
+ return sb.toString();
+ }
+
+
+ /**
+ * Gets the calendar. It could be used to manipulate this
+ * {@link GeneralizedTime} settings.
+ *
+ * @return the calendar
+ */
+ public Calendar getCalendar()
+ {
+ return calendar;
+ }
+
+
+ @Override
+ public String toString()
+ {
+ return toGeneralizedTime();
+ }
+
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + calendar.hashCode();
+ return result;
+ }
+
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( obj instanceof GeneralizedTime )
+ {
+ GeneralizedTime other = ( GeneralizedTime ) obj;
+ return calendar.equals( other.calendar );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ /**
+ * Compares this GeneralizedTime object with the specified GeneralizedTime object.
+ *
+ * @param other the other GeneralizedTime object
+ *
+ * @return a negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo( GeneralizedTime other )
+ {
+ return calendar.compareTo( other.calendar );
+ }
+
+}
Added: directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java?rev=686726&view=auto
==============================================================================
--- directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java (added)
+++ directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java Mon Aug 18 04:26:51 2008
@@ -0,0 +1,1043 @@
+/*
+ * 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.directory.shared.ldap.util;
+
+
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+import org.apache.directory.shared.ldap.schema.syntax.GeneralizedTimeSyntaxCheckerTest;
+import org.apache.directory.shared.ldap.util.GeneralizedTime.Format;
+import org.apache.directory.shared.ldap.util.GeneralizedTime.TimeZoneFormat;
+
+
+/**
+ * Tests the DateUtils class methods.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 542077 $
+ */
+public class GeneralizedTimeTest extends TestCase
+{
+
+ // Test all valid variants:
+ // Time: min + sec / min + no sec / no min + no sec
+ // Fraction: no fraction, dot, comma
+ // Timezone: Z / +HH / +HHmm / -HH / -HHmm
+
+ /**
+ * Tests yyyyMMddHHmmssZ.
+ */
+ public void testYearMonthDayHourMinSecZulu() throws ParseException
+ {
+ String gt = "20080102121314Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss+04.
+ */
+ public void testYearMonthDayHourMinSecPlusHour() throws ParseException
+ {
+ String gt = "20080102121314+04";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss-1030.
+ */
+ public void testYearMonthDayHourMinSecMinusHourMin() throws ParseException
+ {
+ String gt = "20080102121314-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss.SSSZ.
+ */
+ public void testYearMonthDayHourMinSecDotFractionZulu() throws ParseException
+ {
+ String gt = "20080102121314.987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss.SSS+0100.
+ */
+ public void testYearMonthDayHourMinSecDotFractionPlusHour() throws ParseException
+ {
+ String gt = "20080102121314.987+0100";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss.SSS-1030.
+ */
+ public void testYearMonthDayHourMinSecDotFractionMinusHourMin() throws ParseException
+ {
+ String gt = "20080102121314.987-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss,SSSZ.
+ */
+ public void testYearMonthDayHourMinSecCommaFractionZulu() throws ParseException
+ {
+ String gt = "20080102121314,987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss,SSS+0100.
+ */
+ public void testYearMonthDayHourMinSecCommaFractionPlusHour() throws ParseException
+ {
+ String gt = "20080102121314,987+0100";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmss,SSS-1030.
+ */
+ public void testYearMonthDayHourMinSecCommaFractionMinusHourMin() throws ParseException
+ {
+ String gt = "20080102121314,987-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmmZ.
+ */
+ public void testYearMonthDayHourMinZulu() throws ParseException
+ {
+ String gt = "200801021213Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm+HH.
+ */
+ public void testYearMonthDayHourMinPlusHour() throws ParseException
+ {
+ String gt = "200801021213+04";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm-HHmm.
+ */
+ public void testYearMonthDayHourMinMinusHourMin() throws ParseException
+ {
+ String gt = "200801021213-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm.SSSZ.
+ */
+ public void testYearMonthDayHourMinDotFractionZulu() throws ParseException
+ {
+ String gt = "200801021213.987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm.SSS+0100.
+ */
+ public void testYearMonthDayHourMinDotFractionPlusHour() throws ParseException
+ {
+ String gt = "200801021213.987+0100";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm.SSS-1030.
+ */
+ public void testYearMonthDayHourMinDotFractionMinusHourMin() throws ParseException
+ {
+ String gt = "200801021213.987-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm,SSSZ.
+ */
+ public void testYearMonthDayHourMinCommaFractionZulu() throws ParseException
+ {
+ String gt = "200801021213,987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm,SSS+0100.
+ */
+ public void testYearMonthDayHourMinCommaFractionPlusHour() throws ParseException
+ {
+ String gt = "200801021213,987+0100";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHmm,SSS-1030.
+ */
+ public void testYearMonthDayHourMinCommaFractionMinusHourMin() throws ParseException
+ {
+ String gt = "200801021213,987-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHHZ.
+ */
+ public void testYearMonthDayHourZulu() throws ParseException
+ {
+ String gt = "2008010212Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH+HH.
+ */
+ public void testYearMonthDayHourPlusHour() throws ParseException
+ {
+ String gt = "2008010212+04";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH-HHmm.
+ */
+ public void testYearMonthDayHourMinusHourMin() throws ParseException
+ {
+ String gt = "2008010212-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH.SSSZ.
+ */
+ public void testYearMonthDayHourDotFractionZulu() throws ParseException
+ {
+ String gt = "200801021213.987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH.SSS+0100.
+ */
+ public void testYearMonthDayHourDotFractionPlusHour() throws ParseException
+ {
+ String gt = "2008010212.987+0100";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH.SSS-1030.
+ */
+ public void testYearMonthDayHourDotFractionMinusHourMin() throws ParseException
+ {
+ String gt = "2008010212.987-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH,SSSZ.
+ */
+ public void testYearMonthDayHourCommaFractionZulu() throws ParseException
+ {
+ String gt = "2008010212,987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH,SSS+0100.
+ */
+ public void testYearMonthDayHourCommaFractionPlusHour() throws ParseException
+ {
+ String gt = "2008010212,987+0100";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests yyyyMMddHH,SSS-1030.
+ */
+ public void testYearMonthDayHourCommaFractionMinusHourMin() throws ParseException
+ {
+ String gt = "2008010212,987-1030";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests fraction of a second.
+ */
+ public void testFractionOfSecond() throws ParseException
+ {
+ String gt = "20080102121314,987Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ assertEquals( 987, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+ }
+
+
+ /**
+ * Tests fraction of a minute.
+ */
+ public void testFractionOfMinute1() throws ParseException
+ {
+ String gt = "200801021213,5Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ assertEquals( 30, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+ assertEquals( 0, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+ }
+
+
+ /**
+ * Tests fraction of a minute.
+ */
+ public void testFractionOfMinute2() throws ParseException
+ {
+ String gt = "200801021213,125Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ assertEquals( 7, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+ assertEquals( 500, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+ }
+
+
+ /**
+ * Tests fraction of an hour.
+ */
+ public void testFractionOfHour1() throws ParseException
+ {
+ String gt = "2008010212,5Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ assertEquals( 30, generalizedTime.getCalendar().get( Calendar.MINUTE ) );
+ assertEquals( 0, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+ assertEquals( 0, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+ }
+
+
+ /**
+ * Tests fraction of an hour.
+ */
+ public void testFractionOfHour2() throws ParseException
+ {
+ String gt = "2008010212,125Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ assertEquals( 7, generalizedTime.getCalendar().get( Calendar.MINUTE ) );
+ assertEquals( 30, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+ assertEquals( 0, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+ }
+
+
+ /**
+ * Test formatting
+ */
+ public void testFormatting() throws ParseException
+ {
+ String gt = "20080102121314Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+
+ result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR_MIN, null, 0, TimeZoneFormat.Z );
+ assertEquals( "200801021213Z", result );
+
+ result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR, null, 0, TimeZoneFormat.Z );
+ assertEquals( "2008010212Z", result );
+
+ result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR_MIN, null, 0,
+ TimeZoneFormat.DIFF_HOUR_MINUTE );
+ assertEquals( "200801021213+0000", result );
+
+ result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR, null, 0,
+ TimeZoneFormat.DIFF_HOUR_MINUTE );
+ assertEquals( "2008010212+0000", result );
+ }
+
+
+ /**
+ * Testcases from {@link GeneralizedTimeSyntaxCheckerTest#testCorrectCase()}.
+ */
+ public void testGeneralizedTimeSyntaxCheckerTestCorrectCase() throws ParseException
+ {
+ new GeneralizedTime( "20061205184527Z" );
+ new GeneralizedTime( "20061205184527+0500" );
+ new GeneralizedTime( "20061205184527-1234" );
+ new GeneralizedTime( "20061205184527.123Z" );
+ new GeneralizedTime( "20061205184527,123+0100" );
+ new GeneralizedTime( "2006120519Z" );
+ }
+
+
+ /**
+ * Testcases from {@link GeneralizedTimeSyntaxCheckerTest#testErrorCase()}.
+ */
+ public void testGeneralizedTimeSyntaxCheckerTestErrorCase()
+ {
+ try
+ {
+ new GeneralizedTime( "20060005184527Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061305184527Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20062205184527Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061200184527Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061235184527Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205604527Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205186027Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205184561Z" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205184527Z+" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205184527+2400" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205184527+9900" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205184527+1260" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ try
+ {
+ new GeneralizedTime( "20061205184527+1299" );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ }
+
+
+ /**
+ * Tests leap second.
+ * The GeneralizedTime class does not support leap seconds!
+ */
+ public void testLeapSecond() throws ParseException
+ {
+ String gt = "20051231235960Z";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ }
+
+
+ /**
+ * Tests Feb 29 in a leap year.
+ */
+ public void testFebruary29inLeapYear() throws ParseException
+ {
+ String gt = "20080229000000Z";
+ GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( gt, result );
+ }
+
+
+ /**
+ * Tests Feb 29 in a non-leap year.
+ */
+ public void testFebruary29inNonLeapYear() throws ParseException
+ {
+ String gt = "20070229000000Z";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ }
+
+
+ /**
+ * Tests null.
+ */
+ public void testNull() throws ParseException
+ {
+ try
+ {
+ String gt = null;
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ try
+ {
+ Calendar calendar = null;
+ new GeneralizedTime( calendar );
+ fail( "Expected IllegalArgumentException" );
+ }
+ catch ( IllegalArgumentException iae )
+ {
+ // expected
+ }
+
+ }
+
+
+ /**
+ * Tests empty string.
+ */
+ public void testEmpty() throws ParseException
+ {
+ String gt = "";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ }
+
+
+ /**
+ * Tests invalid cases.
+ */
+ public void testInvalid() throws ParseException
+ {
+ // too short year
+ String gt = "200";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // non-digits in year
+ gt = "2XX8";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // too short month
+ gt = "20081";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // non-digits in month
+ gt = "20081X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // too short day
+ gt = "2008122";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // non-digits in day
+ gt = "2008122X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // too short hour
+ gt = "200812211";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // non-digits in hour
+ gt = "20081221X1";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // too short minute
+ gt = "20081221121";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // non-digits in minute
+ gt = "20081221121X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // too short second
+ gt = "2008122112131";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // non-digits in minute
+ gt = "2008122112131X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // missing time zone
+ gt = "2008010212";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // missing time zone
+ gt = "200801021213";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // missing time zone
+ gt = "20080102121314";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // no digit
+ gt = "2008010212X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // no digit
+ gt = "200801021213X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // no digit
+ gt = "20080102121314X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // missing time zone
+ gt = "20080102121314,1";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // time zone is not last char
+ gt = "20080102121314ZX";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // time zone is not last char
+ gt = "20080102121314+0430X";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+
+ // no fraction digit
+ gt = "20080102121314,Z";
+ try
+ {
+ new GeneralizedTime( gt );
+ fail( "Expected ParseException" );
+ }
+ catch ( ParseException pe )
+ {
+ // expected
+ }
+ }
+
+
+ /**
+ * Tests constructor with calendar object.
+ */
+ public void testCalendar() throws ParseException
+ {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set( Calendar.YEAR, 2008 );
+ calendar.set( Calendar.MONTH, 0 );
+ calendar.set( Calendar.DAY_OF_MONTH, 2 );
+ calendar.set( Calendar.HOUR_OF_DAY, 12 );
+ calendar.set( Calendar.MINUTE, 13 );
+ calendar.set( Calendar.SECOND, 14 );
+ calendar.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
+
+ GeneralizedTime generalizedTime = new GeneralizedTime( calendar );
+ String result = generalizedTime.toGeneralizedTime();
+ assertEquals( "20080102121314Z", result );
+
+ }
+
+
+ /**
+ * Tests the compareTo() method.
+ */
+ public void testCompareTo() throws ParseException
+ {
+ String gt1 = "20080102121313,999Z";
+ GeneralizedTime generalizedTime1 = new GeneralizedTime( gt1 );
+
+ String gt2 = "20080102121314Z";
+ GeneralizedTime generalizedTime2 = new GeneralizedTime( gt2 );
+
+ String gt3 = "20080102121314,001Z";
+ GeneralizedTime generalizedTime3 = new GeneralizedTime( gt3 );
+
+ assertTrue( generalizedTime1.compareTo( generalizedTime2 ) < 0 );
+ assertTrue( generalizedTime1.compareTo( generalizedTime3 ) < 0 );
+ assertTrue( generalizedTime2.compareTo( generalizedTime3 ) < 0 );
+
+ assertTrue( generalizedTime2.compareTo( generalizedTime1 ) > 0 );
+ assertTrue( generalizedTime3.compareTo( generalizedTime1 ) > 0 );
+ assertTrue( generalizedTime3.compareTo( generalizedTime2 ) > 0 );
+
+ assertTrue( generalizedTime1.compareTo( generalizedTime1 ) == 0 );
+ assertTrue( generalizedTime2.compareTo( generalizedTime2 ) == 0 );
+ assertTrue( generalizedTime3.compareTo( generalizedTime3 ) == 0 );
+ }
+
+
+ /**
+ * Tests the equals() method.
+ */
+ public void testEquals() throws ParseException
+ {
+ String gt1 = "20080102121314Z";
+ GeneralizedTime generalizedTime1 = new GeneralizedTime( gt1 );
+
+ String gt2 = "20080102121314Z";
+ GeneralizedTime generalizedTime2 = new GeneralizedTime( gt2 );
+
+ String gt3 = "20080102121314,001Z";
+ GeneralizedTime generalizedTime3 = new GeneralizedTime( gt3 );
+
+ assertTrue( generalizedTime1.equals( generalizedTime2 ) );
+ assertFalse( generalizedTime1.equals( generalizedTime3 ) );
+ assertFalse( generalizedTime1.equals( null ) );
+ }
+}