From 8bbc46b9514f49ebf4b9533688ca296046563ef9 Mon Sep 17 00:00:00 2001
From: Gerald Barker Date and time formatting utilities and constants. Formatting is performed using the thread-safe
- * {@link org.apache.commons.lang3.time.FastDateFormat} class. DateFormatUtils instances should NOT be constructed in standard programming. This constructor is public to permit tools that require a JavaBean instance
- * to operate. Formats a date/time into a specific pattern using the UTC time zone. Formats a date/time into a specific pattern using the UTC time zone. Formats a date/time into a specific pattern using the UTC time zone. Formats a date/time into a specific pattern using the UTC time zone. Formats a date/time into a specific pattern. Formats a date/time into a specific pattern. Formats a calendar into a specific pattern. Formats a date/time into a specific pattern in a time zone. Formats a date/time into a specific pattern in a time zone. Formats a calendar into a specific pattern in a time zone. Formats a date/time into a specific pattern in a locale. Formats a date/time into a specific pattern in a locale. Formats a calendar into a specific pattern in a locale. Formats a date/time into a specific pattern in a time zone and locale. Formats a date/time into a specific pattern in a time zone and locale. Formats a calendar into a specific pattern in a time zone and locale. A suite of utilities surrounding the use of the
- * {@link java.util.Calendar} and {@link java.util.Date} object. DateUtils contains a lot of common methods considering manipulations
- * of Dates or Calendars. Some methods require some extra explanation.
- * The truncate, ceiling and round methods could be considered the Math.floor(),
- * Math.ceil() or Math.round versions for dates
- * This way date-fields will be ignored in bottom-up order.
- * As a complement to these methods we've introduced some fragment-methods.
- * With these methods the Date-fields will be ignored in top-down order.
- * Since a date without a year is not a valid date, you have to decide in what
- * kind of date-field you want your result, for instance milliseconds or days.
- * {@code DateUtils} instances should NOT be constructed in
- * standard programming. Instead, the static methods on the class should
- * be used, such as {@code DateUtils.parseDate(str);}. This constructor is public to permit tools that require a JavaBean
- * instance to operate. Checks if two date objects are on the same day ignoring time. 28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true.
- * 28 Mar 2002 13:45 and 12 Mar 2002 13:45 would return false.
- * Checks if two calendar objects are on the same day ignoring time. 28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true.
- * 28 Mar 2002 13:45 and 12 Mar 2002 13:45 would return false.
- * Checks if two date objects represent the same instant in time. This method compares the long millisecond time of the two objects. Checks if two calendar objects represent the same instant in time. This method compares the long millisecond time of the two objects. Checks if two calendar objects represent the same local time. This method compares the values of the fields of the two objects.
- * In addition, both calendars must be the same of the same type. Parses a string representing a date by trying a variety of different parsers. The parse will try each parse pattern in turn.
- * A parse is only deemed successful if it parses the whole of the input string.
- * If no parse patterns match, a ParseException is thrown. Parses a string representing a date by trying a variety of different parsers. The parse will try each parse pattern in turn.
- * A parse is only deemed successful if it parses the whole of the input string.
- * If no parse patterns match, a ParseException is thrown. Parses a string representing a date by trying a variety of different parsers. The parse will try each parse pattern in turn.
- * A parse is only deemed successful if it parses the whole of the input string.
- * If no parse patterns match, a ParseException is thrown. Round this date, leaving the field specified as the most
- * significant field. For example, if you had the datetime of 28 Mar 2002
- * 13:45:01.231, if this was passed with HOUR, it would return
- * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
- * would return 1 April 2002 0:00:00.000. For a date in a timezone that handles the change to daylight
- * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
- * Suppose daylight saving time begins at 02:00 on March 30. Rounding a
- * date that crosses this time would produce the following values:
- * null
- * @return the formatted date
- */
- public static String formatUTC(long millis, String pattern, Locale locale) {
- return format(new Date(millis), pattern, UTC_TIME_ZONE, locale);
- }
-
- /**
- * null
- * @return the formatted date
- */
- public static String formatUTC(Date date, String pattern, Locale locale) {
- return format(date, pattern, UTC_TIME_ZONE, locale);
- }
-
- /**
- * null
- * @return the formatted date
- */
- public static String format(long millis, String pattern, TimeZone timeZone) {
- return format(new Date(millis), pattern, timeZone, null);
- }
-
- /**
- * null
- * @return the formatted date
- */
- public static String format(Date date, String pattern, TimeZone timeZone) {
- return format(date, pattern, timeZone, null);
- }
-
- /**
- * null
- * @return the formatted calendar
- * @see FastDateFormat#format(Calendar)
- * @since 2.4
- */
- public static String format(Calendar calendar, String pattern, TimeZone timeZone) {
- return format(calendar, pattern, timeZone, null);
- }
-
- /**
- * null
- * @return the formatted date
- */
- public static String format(long millis, String pattern, Locale locale) {
- return format(new Date(millis), pattern, null, locale);
- }
-
- /**
- * null
- * @return the formatted date
- */
- public static String format(Date date, String pattern, Locale locale) {
- return format(date, pattern, null, locale);
- }
-
- /**
- * null
- * @return the formatted calendar
- * @see FastDateFormat#format(Calendar)
- * @since 2.4
- */
- public static String format(Calendar calendar, String pattern, Locale locale) {
- return format(calendar, pattern, null, locale);
- }
-
- /**
- * null
- * @param locale the locale to use, may be null
- * @return the formatted date
- */
- public static String format(long millis, String pattern, TimeZone timeZone, Locale locale) {
- return format(new Date(millis), pattern, timeZone, locale);
- }
-
- /**
- * null
- * @param locale the locale to use, may be null
- * @return the formatted date
- */
- public static String format(Date date, String pattern, TimeZone timeZone, Locale locale) {
- FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
- return df.format(date);
- }
-
- /**
- * null
- * @param locale the locale to use, may be null
- * @return the formatted calendar
- * @see FastDateFormat#format(Calendar)
- * @since 2.4
- */
- public static String format(Calendar calendar, String pattern, TimeZone timeZone, Locale locale) {
- FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
- return df.format(calendar);
- }
-
-}
diff --git a/src/org/apache/commons/lang3/time/DateUtils.java b/src/org/apache/commons/lang3/time/DateUtils.java
deleted file mode 100644
index 578d3a3..0000000
--- a/src/org/apache/commons/lang3/time/DateUtils.java
+++ /dev/null
@@ -1,1831 +0,0 @@
-/*
- * 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.commons.lang3.time;
-
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * null
- * @since 2.1
- */
- public static boolean isSameDay(Date date1, Date date2) {
- if (date1 == null || date2 == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar cal1 = Calendar.getInstance();
- cal1.setTime(date1);
- Calendar cal2 = Calendar.getInstance();
- cal2.setTime(date2);
- return isSameDay(cal1, cal2);
- }
-
- /**
- * null
- * @since 2.1
- */
- public static boolean isSameDay(Calendar cal1, Calendar cal2) {
- if (cal1 == null || cal2 == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
- cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
- cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
- }
-
- //-----------------------------------------------------------------------
- /**
- * null
- * @since 2.1
- */
- public static boolean isSameInstant(Date date1, Date date2) {
- if (date1 == null || date2 == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- return date1.getTime() == date2.getTime();
- }
-
- /**
- * null
- * @since 2.1
- */
- public static boolean isSameInstant(Calendar cal1, Calendar cal2) {
- if (cal1 == null || cal2 == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- return cal1.getTime().getTime() == cal2.getTime().getTime();
- }
-
- //-----------------------------------------------------------------------
- /**
- * null
- * @since 2.1
- */
- public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) {
- if (cal1 == null || cal2 == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND) &&
- cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND) &&
- cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE) &&
- cal1.get(Calendar.HOUR_OF_DAY) == cal2.get(Calendar.HOUR_OF_DAY) &&
- cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
- cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
- cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
- cal1.getClass() == cal2.getClass());
- }
-
- //-----------------------------------------------------------------------
- /**
- *
- *
- *
Round this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if this was passed with HOUR, it would return - * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it - * would return 1 April 2002 0:00:00.000.
- * - *For a date in a timezone that handles the change to daylight - * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows. - * Suppose daylight saving time begins at 02:00 on March 30. Rounding a - * date that crosses this time would produce the following values: - *
SEMI_MONTH
- * @return the different rounded date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ArithmeticException if the year is over 280 million
- */
- public static Calendar round(Calendar date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar rounded = (Calendar) date.clone();
- modify(rounded, field, MODIFY_ROUND);
- return rounded;
- }
-
- /**
- * Round this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if this was passed with HOUR, it would return - * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it - * would return 1 April 2002 0:00:00.000.
- * - *For a date in a timezone that handles the change to daylight - * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows. - * Suppose daylight saving time begins at 02:00 on March 30. Rounding a - * date that crosses this time would produce the following values: - *
SEMI_MONTH
- * @return the different rounded date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ClassCastException if the object type is not a {@code Date} or {@code Calendar}
- * @throws ArithmeticException if the year is over 280 million
- */
- public static Date round(Object date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- if (date instanceof Date) {
- return round((Date) date, field);
- } else if (date instanceof Calendar) {
- return round((Calendar) date, field).getTime();
- } else {
- throw new ClassCastException("Could not round " + date);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Truncate this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if you passed with HOUR, it would return 28 Mar - * 2002 13:00:00.000. If this was passed with MONTH, it would - * return 1 Mar 2002 0:00:00.000.
- * - * @param date the date to work with, not null - * @param field the field from {@code Calendar} orSEMI_MONTH
- * @return the different truncated date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ArithmeticException if the year is over 280 million
- */
- public static Date truncate(Date date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar gval = Calendar.getInstance();
- gval.setTime(date);
- modify(gval, field, MODIFY_TRUNCATE);
- return gval.getTime();
- }
-
- /**
- * Truncate this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if you passed with HOUR, it would return 28 Mar - * 2002 13:00:00.000. If this was passed with MONTH, it would - * return 1 Mar 2002 0:00:00.000.
- * - * @param date the date to work with, not null - * @param field the field from {@code Calendar} orSEMI_MONTH
- * @return the different truncated date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ArithmeticException if the year is over 280 million
- */
- public static Calendar truncate(Calendar date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar truncated = (Calendar) date.clone();
- modify(truncated, field, MODIFY_TRUNCATE);
- return truncated;
- }
-
- /**
- * Truncate this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if you passed with HOUR, it would return 28 Mar - * 2002 13:00:00.000. If this was passed with MONTH, it would - * return 1 Mar 2002 0:00:00.000.
- * - * @param date the date to work with, either {@code Date} or {@code Calendar}, not null - * @param field the field from {@code Calendar} orSEMI_MONTH
- * @return the different truncated date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ClassCastException if the object type is not a {@code Date} or {@code Calendar}
- * @throws ArithmeticException if the year is over 280 million
- */
- public static Date truncate(Object date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- if (date instanceof Date) {
- return truncate((Date) date, field);
- } else if (date instanceof Calendar) {
- return truncate((Calendar) date, field).getTime();
- } else {
- throw new ClassCastException("Could not truncate " + date);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Ceil this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if you passed with HOUR, it would return 28 Mar - * 2002 14:00:00.000. If this was passed with MONTH, it would - * return 1 Apr 2002 0:00:00.000.
- * - * @param date the date to work with, not null - * @param field the field from {@code Calendar} orSEMI_MONTH
- * @return the different ceil date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ArithmeticException if the year is over 280 million
- * @since 2.5
- */
- public static Date ceiling(Date date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar gval = Calendar.getInstance();
- gval.setTime(date);
- modify(gval, field, MODIFY_CEILING);
- return gval.getTime();
- }
-
- /**
- * Ceil this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if you passed with HOUR, it would return 28 Mar - * 2002 13:00:00.000. If this was passed with MONTH, it would - * return 1 Mar 2002 0:00:00.000.
- * - * @param date the date to work with, not null - * @param field the field from {@code Calendar} orSEMI_MONTH
- * @return the different ceil date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ArithmeticException if the year is over 280 million
- * @since 2.5
- */
- public static Calendar ceiling(Calendar date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar ceiled = (Calendar) date.clone();
- modify(ceiled, field, MODIFY_CEILING);
- return ceiled;
- }
-
- /**
- * Ceil this date, leaving the field specified as the most - * significant field.
- * - *For example, if you had the datetime of 28 Mar 2002 - * 13:45:01.231, if you passed with HOUR, it would return 28 Mar - * 2002 13:00:00.000. If this was passed with MONTH, it would - * return 1 Mar 2002 0:00:00.000.
- * - * @param date the date to work with, either {@code Date} or {@code Calendar}, not null - * @param field the field from {@code Calendar} orSEMI_MONTH
- * @return the different ceil date, not null
- * @throws IllegalArgumentException if the date is null
- * @throws ClassCastException if the object type is not a {@code Date} or {@code Calendar}
- * @throws ArithmeticException if the year is over 280 million
- * @since 2.5
- */
- public static Date ceiling(Object date, int field) {
- if (date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- if (date instanceof Date) {
- return ceiling((Date) date, field);
- } else if (date instanceof Calendar) {
- return ceiling((Calendar) date, field).getTime();
- } else {
- throw new ClassCastException("Could not find ceiling of for type: " + date.getClass());
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Internal calculation method.
- * - * @param val the calendar, not null - * @param field the field constant - * @param modType type to truncate, round or ceiling - * @throws ArithmeticException if the year is over 280 million - */ - private static void modify(Calendar val, int field, int modType) { - if (val.get(Calendar.YEAR) > 280000000) { - throw new ArithmeticException("Calendar value too large for accurate calculations"); - } - - if (field == Calendar.MILLISECOND) { - return; - } - - // ----------------- Fix for LANG-59 ---------------------- START --------------- - // see http://issues.apache.org/jira/browse/LANG-59 - // - // Manually truncate milliseconds, seconds and minutes, rather than using - // Calendar methods. - - Date date = val.getTime(); - long time = date.getTime(); - boolean done = false; - - // truncate milliseconds - int millisecs = val.get(Calendar.MILLISECOND); - if (MODIFY_TRUNCATE == modType || millisecs < 500) { - time = time - millisecs; - } - if (field == Calendar.SECOND) { - done = true; - } - - // truncate seconds - int seconds = val.get(Calendar.SECOND); - if (!done && (MODIFY_TRUNCATE == modType || seconds < 30)) { - time = time - (seconds * 1000L); - } - if (field == Calendar.MINUTE) { - done = true; - } - - // truncate minutes - int minutes = val.get(Calendar.MINUTE); - if (!done && (MODIFY_TRUNCATE == modType || minutes < 30)) { - time = time - (minutes * 60000L); - } - - // reset time - if (date.getTime() != time) { - date.setTime(time); - val.setTime(date); - } - // ----------------- Fix for LANG-59 ----------------------- END ---------------- - - boolean roundUp = false; - for (int[] aField : fields) { - for (int element : aField) { - if (element == field) { - //This is our field... we stop looping - if (modType == MODIFY_CEILING || (modType == MODIFY_ROUND && roundUp)) { - if (field == DateUtils.SEMI_MONTH) { - //This is a special case that's hard to generalize - //If the date is 1, we round up to 16, otherwise - // we subtract 15 days and add 1 month - if (val.get(Calendar.DATE) == 1) { - val.add(Calendar.DATE, 15); - } else { - val.add(Calendar.DATE, -15); - val.add(Calendar.MONTH, 1); - } -// ----------------- Fix for LANG-440 ---------------------- START --------------- - } else if (field == Calendar.AM_PM) { - // This is a special case - // If the time is 0, we round up to 12, otherwise - // we subtract 12 hours and add 1 day - if (val.get(Calendar.HOUR_OF_DAY) == 0) { - val.add(Calendar.HOUR_OF_DAY, 12); - } else { - val.add(Calendar.HOUR_OF_DAY, -12); - val.add(Calendar.DATE, 1); - } -// ----------------- Fix for LANG-440 ---------------------- END --------------- - } else { - //We need at add one to this field since the - // last number causes us to round up - val.add(aField[0], 1); - } - } - return; - } - } - //We have various fields that are not easy roundings - int offset = 0; - boolean offsetSet = false; - //These are special types of fields that require different rounding rules - switch (field) { - case DateUtils.SEMI_MONTH: - if (aField[0] == Calendar.DATE) { - //If we're going to drop the DATE field's value, - // we want to do this our own way. - //We need to subtrace 1 since the date has a minimum of 1 - offset = val.get(Calendar.DATE) - 1; - //If we're above 15 days adjustment, that means we're in the - // bottom half of the month and should stay accordingly. - if (offset >= 15) { - offset -= 15; - } - //Record whether we're in the top or bottom half of that range - roundUp = offset > 7; - offsetSet = true; - } - break; - case Calendar.AM_PM: - if (aField[0] == Calendar.HOUR_OF_DAY) { - //If we're going to drop the HOUR field's value, - // we want to do this our own way. - offset = val.get(Calendar.HOUR_OF_DAY); - if (offset >= 12) { - offset -= 12; - } - roundUp = offset >= 6; - offsetSet = true; - } - break; - } - if (!offsetSet) { - int min = val.getActualMinimum(aField[0]); - int max = val.getActualMaximum(aField[0]); - //Calculate the offset from the minimum allowed value - offset = val.get(aField[0]) - min; - //Set roundUp if this is more than half way between the minimum and maximum - roundUp = offset > ((max - min) / 2); - } - //We need to remove this field - if (offset != 0) { - val.set(aField[0], val.get(aField[0]) - offset); - } - } - throw new IllegalArgumentException("The field " + field + " is not supported"); - - } - - //----------------------------------------------------------------------- - /** - *This constructs an Iterator over each day in a date
- * range defined by a focus date and range style.
For instance, passing Thursday, July 4, 2002 and a
- * RANGE_MONTH_SUNDAY will return an Iterator
- * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
- * 2002, returning a Calendar instance for each intermediate day.
This method provides an iterator that returns Calendar objects. - * The days are progressed using {@link Calendar#add(int, int)}.
- * - * @param focus the date to work with, not null - * @param rangeStyle the style constant to use. Must be one of - * {@link DateUtils#RANGE_MONTH_SUNDAY}, - * {@link DateUtils#RANGE_MONTH_MONDAY}, - * {@link DateUtils#RANGE_WEEK_SUNDAY}, - * {@link DateUtils#RANGE_WEEK_MONDAY}, - * {@link DateUtils#RANGE_WEEK_RELATIVE}, - * {@link DateUtils#RANGE_WEEK_CENTER} - * @return the date iterator, not null, not null - * @throws IllegalArgumentException if the date isnull
- * @throws IllegalArgumentException if the rangeStyle is invalid
- */
- public static IteratorThis constructs an Iterator over each day in a date
- * range defined by a focus date and range style.
For instance, passing Thursday, July 4, 2002 and a
- * RANGE_MONTH_SUNDAY will return an Iterator
- * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
- * 2002, returning a Calendar instance for each intermediate day.
This method provides an iterator that returns Calendar objects. - * The days are progressed using {@link Calendar#add(int, int)}.
- * - * @param focus the date to work with, not null - * @param rangeStyle the style constant to use. Must be one of - * {@link DateUtils#RANGE_MONTH_SUNDAY}, - * {@link DateUtils#RANGE_MONTH_MONDAY}, - * {@link DateUtils#RANGE_WEEK_SUNDAY}, - * {@link DateUtils#RANGE_WEEK_MONDAY}, - * {@link DateUtils#RANGE_WEEK_RELATIVE}, - * {@link DateUtils#RANGE_WEEK_CENTER} - * @return the date iterator, not null - * @throws IllegalArgumentException if the date isnull
- * @throws IllegalArgumentException if the rangeStyle is invalid
- */
- public static IteratorThis constructs an Iterator over each day in a date
- * range defined by a focus date and range style.
For instance, passing Thursday, July 4, 2002 and a
- * RANGE_MONTH_SUNDAY will return an Iterator
- * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
- * 2002, returning a Calendar instance for each intermediate day.
null
- * @throws ClassCastException if the object type is not a {@code Date} or {@code Calendar}
- */
- public static Iterator> iterator(Object focus, int rangeStyle) {
- if (focus == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- if (focus instanceof Date) {
- return iterator((Date) focus, rangeStyle);
- } else if (focus instanceof Calendar) {
- return iterator((Calendar) focus, rangeStyle);
- } else {
- throw new ClassCastException("Could not iterate based on " + focus);
- }
- }
-
- /**
- * Returns the number of milliseconds within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the milliseconds of any date will only return the number of milliseconds - * of the current second (resulting in a number between 0 and 999). This - * method will retrieve the number of milliseconds for any fragment. - * For example, if you want to calculate the number of milliseconds past today, - * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will - * be all milliseconds of the past hour(s), minutes(s) and second(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a SECOND field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInMilliseconds(Date date, int fragment) {
- return getFragment(date, fragment, Calendar.MILLISECOND);
- }
-
- /**
- * Returns the number of seconds within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the seconds of any date will only return the number of seconds - * of the current minute (resulting in a number between 0 and 59). This - * method will retrieve the number of seconds for any fragment. - * For example, if you want to calculate the number of seconds past today, - * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will - * be all seconds of the past hour(s) and minutes(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a SECOND field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInSeconds(Date date, int fragment) {
- return getFragment(date, fragment, Calendar.SECOND);
- }
-
- /**
- * Returns the number of minutes within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the minutes of any date will only return the number of minutes - * of the current hour (resulting in a number between 0 and 59). This - * method will retrieve the number of minutes for any fragment. - * For example, if you want to calculate the number of minutes past this month, - * your fragment is Calendar.MONTH. The result will be all minutes of the - * past day(s) and hour(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a MINUTE field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInMinutes(Date date, int fragment) {
- return getFragment(date, fragment, Calendar.MINUTE);
- }
-
- /**
- * Returns the number of hours within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the hours of any date will only return the number of hours - * of the current day (resulting in a number between 0 and 23). This - * method will retrieve the number of hours for any fragment. - * For example, if you want to calculate the number of hours past this month, - * your fragment is Calendar.MONTH. The result will be all hours of the - * past day(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a HOUR field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInHours(Date date, int fragment) {
- return getFragment(date, fragment, Calendar.HOUR_OF_DAY);
- }
-
- /**
- * Returns the number of days within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the days of any date will only return the number of days - * of the current month (resulting in a number between 1 and 31). This - * method will retrieve the number of days for any fragment. - * For example, if you want to calculate the number of days past this year, - * your fragment is Calendar.YEAR. The result will be all days of the - * past month(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a DAY field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInDays(Date date, int fragment) {
- return getFragment(date, fragment, Calendar.DAY_OF_YEAR);
- }
-
- /**
- * Returns the number of milliseconds within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the milliseconds of any date will only return the number of milliseconds - * of the current second (resulting in a number between 0 and 999). This - * method will retrieve the number of milliseconds for any fragment. - * For example, if you want to calculate the number of seconds past today, - * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will - * be all seconds of the past hour(s), minutes(s) and second(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a MILLISECOND field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInMilliseconds(Calendar calendar, int fragment) {
- return getFragment(calendar, fragment, Calendar.MILLISECOND);
- }
- /**
- * Returns the number of seconds within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the seconds of any date will only return the number of seconds - * of the current minute (resulting in a number between 0 and 59). This - * method will retrieve the number of seconds for any fragment. - * For example, if you want to calculate the number of seconds past today, - * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will - * be all seconds of the past hour(s) and minutes(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a SECOND field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInSeconds(Calendar calendar, int fragment) {
- return getFragment(calendar, fragment, Calendar.SECOND);
- }
-
- /**
- * Returns the number of minutes within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the minutes of any date will only return the number of minutes - * of the current hour (resulting in a number between 0 and 59). This - * method will retrieve the number of minutes for any fragment. - * For example, if you want to calculate the number of minutes past this month, - * your fragment is Calendar.MONTH. The result will be all minutes of the - * past day(s) and hour(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a MINUTE field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInMinutes(Calendar calendar, int fragment) {
- return getFragment(calendar, fragment, Calendar.MINUTE);
- }
-
- /**
- * Returns the number of hours within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the hours of any date will only return the number of hours - * of the current day (resulting in a number between 0 and 23). This - * method will retrieve the number of hours for any fragment. - * For example, if you want to calculate the number of hours past this month, - * your fragment is Calendar.MONTH. The result will be all hours of the - * past day(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a HOUR field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInHours(Calendar calendar, int fragment) {
- return getFragment(calendar, fragment, Calendar.HOUR_OF_DAY);
- }
-
- /**
- * Returns the number of days within the - * fragment. All datefields greater than the fragment will be ignored.
- * - *Asking the days of any date will only return the number of days - * of the current month (resulting in a number between 1 and 31). This - * method will retrieve the number of days for any fragment. - * For example, if you want to calculate the number of days past this year, - * your fragment is Calendar.YEAR. The result will be all days of the - * past month(s).
- * - *Valid fragments are: Calendar.YEAR, Calendar.MONTH, both - * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, - * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND - * A fragment less than or equal to a DAY field will return 0.
- * - *- *
null or
- * fragment is not supported
- * @since 2.4
- */
- public static long getFragmentInDays(Calendar calendar, int fragment) {
- return getFragment(calendar, fragment, Calendar.DAY_OF_YEAR);
- }
-
- /**
- * Date-version for fragment-calculation in any unit
- *
- * @param date the date to work with, not null
- * @param fragment the Calendar field part of date to calculate
- * @param unit the {@code Calendar} field defining the unit
- * @return number of units within the fragment of the date
- * @throws IllegalArgumentException if the date is null or
- * fragment is not supported
- * @since 2.4
- */
- private static long getFragment(Date date, int fragment, int unit) {
- if(date == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- Calendar calendar = Calendar.getInstance();
- calendar.setTime(date);
- return getFragment(calendar, fragment, unit);
- }
-
- /**
- * Calendar-version for fragment-calculation in any unit
- *
- * @param calendar the calendar to work with, not null
- * @param fragment the Calendar field part of calendar to calculate
- * @param unit the {@code Calendar} field defining the unit
- * @return number of units within the fragment of the calendar
- * @throws IllegalArgumentException if the date is null or
- * fragment is not supported
- * @since 2.4
- */
- private static long getFragment(Calendar calendar, int fragment, int unit) {
- if(calendar == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- long millisPerUnit = getMillisPerUnit(unit);
- long result = 0;
-
- // Fragments bigger than a day require a breakdown to days
- switch (fragment) {
- case Calendar.YEAR:
- result += (calendar.get(Calendar.DAY_OF_YEAR) * MILLIS_PER_DAY) / millisPerUnit;
- break;
- case Calendar.MONTH:
- result += (calendar.get(Calendar.DAY_OF_MONTH) * MILLIS_PER_DAY) / millisPerUnit;
- break;
- }
-
- switch (fragment) {
- // Number of days already calculated for these cases
- case Calendar.YEAR:
- case Calendar.MONTH:
-
- // The rest of the valid cases
- case Calendar.DAY_OF_YEAR:
- case Calendar.DATE:
- result += (calendar.get(Calendar.HOUR_OF_DAY) * MILLIS_PER_HOUR) / millisPerUnit;
- //$FALL-THROUGH$
- case Calendar.HOUR_OF_DAY:
- result += (calendar.get(Calendar.MINUTE) * MILLIS_PER_MINUTE) / millisPerUnit;
- //$FALL-THROUGH$
- case Calendar.MINUTE:
- result += (calendar.get(Calendar.SECOND) * MILLIS_PER_SECOND) / millisPerUnit;
- //$FALL-THROUGH$
- case Calendar.SECOND:
- result += (calendar.get(Calendar.MILLISECOND) * 1) / millisPerUnit;
- break;
- case Calendar.MILLISECOND: break;//never useful
- default: throw new IllegalArgumentException("The fragment " + fragment + " is not supported");
- }
- return result;
- }
-
- /**
- * Determines if two calendars are equal up to no more than the specified
- * most significant field.
- *
- * @param cal1 the first calendar, not null
- * @param cal2 the second calendar, not null
- * @param field the field from {@code Calendar}
- * @return true if equal; otherwise false
- * @throws IllegalArgumentException if any argument is null
- * @see #truncate(Calendar, int)
- * @see #truncatedEquals(Date, Date, int)
- * @since 3.0
- */
- public static boolean truncatedEquals(Calendar cal1, Calendar cal2, int field) {
- return truncatedCompareTo(cal1, cal2, field) == 0;
- }
-
- /**
- * Determines if two dates are equal up to no more than the specified
- * most significant field.
- *
- * @param date1 the first date, not null
- * @param date2 the second date, not null
- * @param field the field from {@code Calendar}
- * @return true if equal; otherwise false
- * @throws IllegalArgumentException if any argument is null
- * @see #truncate(Date, int)
- * @see #truncatedEquals(Calendar, Calendar, int)
- * @since 3.0
- */
- public static boolean truncatedEquals(Date date1, Date date2, int field) {
- return truncatedCompareTo(date1, date2, field) == 0;
- }
-
- /**
- * Determines how two calendars compare up to no more than the specified
- * most significant field.
- *
- * @param cal1 the first calendar, not null
- * @param cal2 the second calendar, not null
- * @param field the field from {@code Calendar}
- * @return a negative integer, zero, or a positive integer as the first
- * calendar is less than, equal to, or greater than the second.
- * @throws IllegalArgumentException if any argument is null
- * @see #truncate(Calendar, int)
- * @see #truncatedCompareTo(Date, Date, int)
- * @since 3.0
- */
- public static int truncatedCompareTo(Calendar cal1, Calendar cal2, int field) {
- Calendar truncatedCal1 = truncate(cal1, field);
- Calendar truncatedCal2 = truncate(cal2, field);
- return truncatedCal1.compareTo(truncatedCal2);
- }
-
- /**
- * Determines how two dates compare up to no more than the specified
- * most significant field.
- *
- * @param date1 the first date, not null
- * @param date2 the second date, not null
- * @param field the field from Calendar
- * @return a negative integer, zero, or a positive integer as the first
- * date is less than, equal to, or greater than the second.
- * @throws IllegalArgumentException if any argument is null
- * @see #truncate(Calendar, int)
- * @see #truncatedCompareTo(Date, Date, int)
- * @since 3.0
- */
- public static int truncatedCompareTo(Date date1, Date date2, int field) {
- Date truncatedDate1 = truncate(date1, field);
- Date truncatedDate2 = truncate(date2, field);
- return truncatedDate1.compareTo(truncatedDate2);
- }
-
- /**
- * Returns the number of milliseconds of a {@code Calendar} field, if this is a constant value.
- * This handles millisecond, second, minute, hour and day (even though days can very in length).
- *
- * @param unit a {@code Calendar} field constant which is a valid unit for a fragment
- * @return the number of milliseconds in the field
- * @throws IllegalArgumentException if date can't be represented in milliseconds
- * @since 2.4
- */
- private static long getMillisPerUnit(int unit) {
- long result = Long.MAX_VALUE;
- switch (unit) {
- case Calendar.DAY_OF_YEAR:
- case Calendar.DATE:
- result = MILLIS_PER_DAY;
- break;
- case Calendar.HOUR_OF_DAY:
- result = MILLIS_PER_HOUR;
- break;
- case Calendar.MINUTE:
- result = MILLIS_PER_MINUTE;
- break;
- case Calendar.SECOND:
- result = MILLIS_PER_SECOND;
- break;
- case Calendar.MILLISECOND:
- result = 1;
- break;
- default: throw new IllegalArgumentException("The unit " + unit + " cannot be represented is milleseconds");
- }
- return result;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Date iterator.
- */ - static class DateIterator implements Iteratortrue if the iterator has yet to reach the end date
- */
- public boolean hasNext() {
- return spot.before(endFinal);
- }
-
- /**
- * Return the next calendar in the iteration
- *
- * @return Object calendar for the next date
- */
- public Calendar next() {
- if (spot.equals(endFinal)) {
- throw new NoSuchElementException();
- }
- spot.add(Calendar.DATE, 1);
- return (Calendar) spot.clone();
- }
-
- /**
- * Always throws UnsupportedOperationException.
- *
- * @throws UnsupportedOperationException
- * @see java.util.Iterator#remove()
- */
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
-}
diff --git a/src/org/apache/commons/lang3/time/DurationFormatUtils.java b/src/org/apache/commons/lang3/time/DurationFormatUtils.java
deleted file mode 100644
index 9f8d622..0000000
--- a/src/org/apache/commons/lang3/time/DurationFormatUtils.java
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * 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.commons.lang3.time;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-
-import org.apache.commons.lang3.StringUtils;
-
-/**
- * Duration formatting utilities and constants. The following table describes the tokens - * used in the pattern language for formatting.
- *| character | duration element |
|---|---|
| y | years |
| M | months |
| d | days |
| H | hours |
| m | minutes |
| s | seconds |
| S | milliseconds |
DurationFormatUtils instances should NOT be constructed in standard programming.
- * - *This constructor is public to permit tools that require a JavaBean instance - * to operate.
- */ - public DurationFormatUtils() { - super(); - } - - /** - *Pattern used with FastDateFormat and SimpleDateFormat
- * for the ISO8601 period format used in durations.
Formats the time gap as a string.
- * - *The format used is ISO8601-like: - * H:m:s.S.
- * - * @param durationMillis the duration to format - * @return the formatted duration, not null - */ - public static String formatDurationHMS(long durationMillis) { - return formatDuration(durationMillis, "H:mm:ss.SSS"); - } - - /** - *Formats the time gap as a string.
- * - *The format used is the ISO8601 period format.
- * - *This method formats durations using the days and lower fields of the - * ISO format pattern, such as P7D6TH5M4.321S.
- * - * @param durationMillis the duration to format - * @return the formatted duration, not null - */ - public static String formatDurationISO(long durationMillis) { - return formatDuration(durationMillis, ISO_EXTENDED_FORMAT_PATTERN, false); - } - - /** - *Formats the time gap as a string, using the specified format, and padding with zeros and - * using the default timezone.
- * - *This method formats durations using the days and lower fields of the - * format pattern. Months and larger are not used.
- * - * @param durationMillis the duration to format - * @param format the way in which to format the duration, not null - * @return the formatted duration, not null - */ - public static String formatDuration(long durationMillis, String format) { - return formatDuration(durationMillis, format, true); - } - - /** - *Formats the time gap as a string, using the specified format. - * Padding the left hand side of numbers with zeroes is optional and - * the timezone may be specified.
- * - *This method formats durations using the days and lower fields of the - * format pattern. Months and larger are not used.
- * - * @param durationMillis the duration to format - * @param format the way in which to format the duration, not null - * @param padWithZeros whether to pad the left hand side of numbers with 0's - * @return the formatted duration, not null - */ - public static String formatDuration(long durationMillis, String format, boolean padWithZeros) { - - Token[] tokens = lexx(format); - - int days = 0; - int hours = 0; - int minutes = 0; - int seconds = 0; - int milliseconds = 0; - - if (Token.containsTokenWithValue(tokens, d) ) { - days = (int) (durationMillis / DateUtils.MILLIS_PER_DAY); - durationMillis = durationMillis - (days * DateUtils.MILLIS_PER_DAY); - } - if (Token.containsTokenWithValue(tokens, H) ) { - hours = (int) (durationMillis / DateUtils.MILLIS_PER_HOUR); - durationMillis = durationMillis - (hours * DateUtils.MILLIS_PER_HOUR); - } - if (Token.containsTokenWithValue(tokens, m) ) { - minutes = (int) (durationMillis / DateUtils.MILLIS_PER_MINUTE); - durationMillis = durationMillis - (minutes * DateUtils.MILLIS_PER_MINUTE); - } - if (Token.containsTokenWithValue(tokens, s) ) { - seconds = (int) (durationMillis / DateUtils.MILLIS_PER_SECOND); - durationMillis = durationMillis - (seconds * DateUtils.MILLIS_PER_SECOND); - } - if (Token.containsTokenWithValue(tokens, S) ) { - milliseconds = (int) durationMillis; - } - - return format(tokens, 0, 0, days, hours, minutes, seconds, milliseconds, padWithZeros); - } - - /** - *Formats an elapsed time into a plurialization correct string.
- * - *This method formats durations using the days and lower fields of the - * format pattern. Months and larger are not used.
- * - * @param durationMillis the elapsed time to report in milliseconds - * @param suppressLeadingZeroElements suppresses leading 0 elements - * @param suppressTrailingZeroElements suppresses trailing 0 elements - * @return the formatted text in days/hours/minutes/seconds, not null - */ - public static String formatDurationWords( - long durationMillis, - boolean suppressLeadingZeroElements, - boolean suppressTrailingZeroElements) { - - // This method is generally replacable by the format method, but - // there are a series of tweaks and special cases that require - // trickery to replicate. - String duration = formatDuration(durationMillis, "d' days 'H' hours 'm' minutes 's' seconds'"); - if (suppressLeadingZeroElements) { - // this is a temporary marker on the front. Like ^ in regexp. - duration = " " + duration; - String tmp = StringUtils.replaceOnce(duration, " 0 days", ""); - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(duration, " 0 hours", ""); - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(duration, " 0 minutes", ""); - duration = tmp; - if (tmp.length() != duration.length()) { - duration = StringUtils.replaceOnce(tmp, " 0 seconds", ""); - } - } - } - if (duration.length() != 0) { - // strip the space off again - duration = duration.substring(1); - } - } - if (suppressTrailingZeroElements) { - String tmp = StringUtils.replaceOnce(duration, " 0 seconds", ""); - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(duration, " 0 minutes", ""); - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(duration, " 0 hours", ""); - if (tmp.length() != duration.length()) { - duration = StringUtils.replaceOnce(tmp, " 0 days", ""); - } - } - } - } - // handle plurals - duration = " " + duration; - duration = StringUtils.replaceOnce(duration, " 1 seconds", " 1 second"); - duration = StringUtils.replaceOnce(duration, " 1 minutes", " 1 minute"); - duration = StringUtils.replaceOnce(duration, " 1 hours", " 1 hour"); - duration = StringUtils.replaceOnce(duration, " 1 days", " 1 day"); - return duration.trim(); - } - - //----------------------------------------------------------------------- - /** - *Formats the time gap as a string.
- * - *The format used is the ISO8601 period format.
- * - * @param startMillis the start of the duration to format - * @param endMillis the end of the duration to format - * @return the formatted duration, not null - */ - public static String formatPeriodISO(long startMillis, long endMillis) { - return formatPeriod(startMillis, endMillis, ISO_EXTENDED_FORMAT_PATTERN, false, TimeZone.getDefault()); - } - - /** - *Formats the time gap as a string, using the specified format. - * Padding the left hand side of numbers with zeroes is optional. - * - * @param startMillis the start of the duration - * @param endMillis the end of the duration - * @param format the way in which to format the duration, not null - * @return the formatted duration, not null - */ - public static String formatPeriod(long startMillis, long endMillis, String format) { - return formatPeriod(startMillis, endMillis, format, true, TimeZone.getDefault()); - } - - /** - *
Formats the time gap as a string, using the specified format. - * Padding the left hand side of numbers with zeroes is optional and - * the timezone may be specified.
- * - *When calculating the difference between months/days, it chooses to - * calculate months first. So when working out the number of months and - * days between January 15th and March 10th, it choose 1 month and - * 23 days gained by choosing January->February = 1 month and then - * calculating days forwards, and not the 1 month and 26 days gained by - * choosing March -> February = 1 month and then calculating days - * backwards.
- * - *For more control, the Joda-Time - * library is recommended.
- * - * @param startMillis the start of the duration - * @param endMillis the end of the duration - * @param format the way in which to format the duration, not null - * @param padWithZeros whether to pad the left hand side of numbers with 0's - * @param timezone the millis are defined in - * @return the formatted duration, not null - */ - public static String formatPeriod(long startMillis, long endMillis, String format, boolean padWithZeros, - TimeZone timezone) { - - // Used to optimise for differences under 28 days and - // called formatDuration(millis, format); however this did not work - // over leap years. - // TODO: Compare performance to see if anything was lost by - // losing this optimisation. - - Token[] tokens = lexx(format); - - // timezones get funky around 0, so normalizing everything to GMT - // stops the hours being off - Calendar start = Calendar.getInstance(timezone); - start.setTime(new Date(startMillis)); - Calendar end = Calendar.getInstance(timezone); - end.setTime(new Date(endMillis)); - - // initial estimates - int milliseconds = end.get(Calendar.MILLISECOND) - start.get(Calendar.MILLISECOND); - int seconds = end.get(Calendar.SECOND) - start.get(Calendar.SECOND); - int minutes = end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE); - int hours = end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY); - int days = end.get(Calendar.DAY_OF_MONTH) - start.get(Calendar.DAY_OF_MONTH); - int months = end.get(Calendar.MONTH) - start.get(Calendar.MONTH); - int years = end.get(Calendar.YEAR) - start.get(Calendar.YEAR); - - // each initial estimate is adjusted in case it is under 0 - while (milliseconds < 0) { - milliseconds += 1000; - seconds -= 1; - } - while (seconds < 0) { - seconds += 60; - minutes -= 1; - } - while (minutes < 0) { - minutes += 60; - hours -= 1; - } - while (hours < 0) { - hours += 24; - days -= 1; - } - - if (Token.containsTokenWithValue(tokens, M)) { - while (days < 0) { - days += start.getActualMaximum(Calendar.DAY_OF_MONTH); - months -= 1; - start.add(Calendar.MONTH, 1); - } - - while (months < 0) { - months += 12; - years -= 1; - } - - if (!Token.containsTokenWithValue(tokens, y) && years != 0) { - while (years != 0) { - months += 12 * years; - years = 0; - } - } - } else { - // there are no M's in the format string - - if( !Token.containsTokenWithValue(tokens, y) ) { - int target = end.get(Calendar.YEAR); - if (months < 0) { - // target is end-year -1 - target -= 1; - } - - while ( (start.get(Calendar.YEAR) != target)) { - days += start.getActualMaximum(Calendar.DAY_OF_YEAR) - start.get(Calendar.DAY_OF_YEAR); - - // Not sure I grok why this is needed, but the brutal tests show it is - if (start instanceof GregorianCalendar && - start.get(Calendar.MONTH) == Calendar.FEBRUARY && - start.get(Calendar.DAY_OF_MONTH) == 29) { - days += 1; - } - - start.add(Calendar.YEAR, 1); - - days += start.get(Calendar.DAY_OF_YEAR); - } - - years = 0; - } - - while( start.get(Calendar.MONTH) != end.get(Calendar.MONTH) ) { - days += start.getActualMaximum(Calendar.DAY_OF_MONTH); - start.add(Calendar.MONTH, 1); - } - - months = 0; - - while (days < 0) { - days += start.getActualMaximum(Calendar.DAY_OF_MONTH); - months -= 1; - start.add(Calendar.MONTH, 1); - } - - } - - // The rest of this code adds in values that - // aren't requested. This allows the user to ask for the - // number of months and get the real count and not just 0->11. - - if (!Token.containsTokenWithValue(tokens, d)) { - hours += 24 * days; - days = 0; - } - if (!Token.containsTokenWithValue(tokens, H)) { - minutes += 60 * hours; - hours = 0; - } - if (!Token.containsTokenWithValue(tokens, m)) { - seconds += 60 * minutes; - minutes = 0; - } - if (!Token.containsTokenWithValue(tokens, s)) { - milliseconds += 1000 * seconds; - seconds = 0; - } - - return format(tokens, years, months, days, hours, minutes, seconds, milliseconds, padWithZeros); - } - - //----------------------------------------------------------------------- - /** - *The internal method to do the formatting.
- * - * @param tokens the tokens - * @param years the number of years - * @param months the number of months - * @param days the number of days - * @param hours the number of hours - * @param minutes the number of minutes - * @param seconds the number of seconds - * @param milliseconds the number of millis - * @param padWithZeros whether to pad - * @return the formatted string - */ - static String format(Token[] tokens, int years, int months, int days, int hours, int minutes, int seconds, - int milliseconds, boolean padWithZeros) { - StringBuffer buffer = new StringBuffer(); - boolean lastOutputSeconds = false; - int sz = tokens.length; - for (int i = 0; i < sz; i++) { - Token token = tokens[i]; - Object value = token.getValue(); - int count = token.getCount(); - if (value instanceof StringBuffer) { - buffer.append(value.toString()); - } else { - if (value == y) { - buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(years), count, '0') : Integer - .toString(years)); - lastOutputSeconds = false; - } else if (value == M) { - buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(months), count, '0') : Integer - .toString(months)); - lastOutputSeconds = false; - } else if (value == d) { - buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(days), count, '0') : Integer - .toString(days)); - lastOutputSeconds = false; - } else if (value == H) { - buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(hours), count, '0') : Integer - .toString(hours)); - lastOutputSeconds = false; - } else if (value == m) { - buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(minutes), count, '0') : Integer - .toString(minutes)); - lastOutputSeconds = false; - } else if (value == s) { - buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(seconds), count, '0') : Integer - .toString(seconds)); - lastOutputSeconds = true; - } else if (value == S) { - if (lastOutputSeconds) { - milliseconds += 1000; - String str = padWithZeros - ? StringUtils.leftPad(Integer.toString(milliseconds), count, '0') - : Integer.toString(milliseconds); - buffer.append(str.substring(1)); - } else { - buffer.append(padWithZeros - ? StringUtils.leftPad(Integer.toString(milliseconds), count, '0') - : Integer.toString(milliseconds)); - } - lastOutputSeconds = false; - } - } - } - return buffer.toString(); - } - - static final Object y = "y"; - static final Object M = "M"; - static final Object d = "d"; - static final Object H = "H"; - static final Object m = "m"; - static final Object s = "s"; - static final Object S = "S"; - - /** - * Parses a classic date format string into Tokens - * - * @param format the format to parse, not null - * @return array of Token[] - */ - static Token[] lexx(String format) { - char[] array = format.toCharArray(); - ArrayListtrue if equal
- */
- @Override
- public boolean equals(Object obj2) {
- if (obj2 instanceof Token) {
- Token tok2 = (Token) obj2;
- if (this.value.getClass() != tok2.value.getClass()) {
- return false;
- }
- if (this.count != tok2.count) {
- return false;
- }
- if (this.value instanceof StringBuffer) {
- return this.value.toString().equals(tok2.value.toString());
- } else if (this.value instanceof Number) {
- return this.value.equals(tok2.value);
- } else {
- return this.value == tok2.value;
- }
- }
- return false;
- }
-
- /**
- * Returns a hash code for the token equal to the
- * hash code for the token's value. Thus 'TT' and 'TTTT'
- * will have the same hash code.
- *
- * @return The hash code for the token
- */
- @Override
- public int hashCode() {
- return this.value.hashCode();
- }
-
- /**
- * Represents this token as a String.
- *
- * @return String representation of the token
- */
- @Override
- public String toString() {
- return StringUtils.repeat(this.value.toString(), this.count);
- }
- }
-
-}
diff --git a/src/org/apache/commons/lang3/time/FastDateFormat.java b/src/org/apache/commons/lang3/time/FastDateFormat.java
deleted file mode 100644
index 3a60527..0000000
--- a/src/org/apache/commons/lang3/time/FastDateFormat.java
+++ /dev/null
@@ -1,1519 +0,0 @@
-/*
- * 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.commons.lang3.time;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.text.DateFormat;
-import java.text.DateFormatSymbols;
-import java.text.FieldPosition;
-import java.text.Format;
-import java.text.ParsePosition;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.apache.commons.lang3.Validate;
-
-/**
- * FastDateFormat is a fast and thread-safe version of - * {@link java.text.SimpleDateFormat}.
- * - *This class can be used as a direct replacement to - * {@code SimpleDateFormat} in most formatting situations. - * This class is especially useful in multi-threaded server environments. - * {@code SimpleDateFormat} is not thread-safe in any JDK version, - * nor will it be as Sun have closed the bug/RFE. - *
- * - *Only formatting is supported, but all patterns are compatible with - * SimpleDateFormat (except time zones and some year patterns - see below).
- * - *Java 1.4 introduced a new pattern letter, {@code 'Z'}, to represent - * time zones in RFC822 format (eg. {@code +0800} or {@code -1100}). - * This pattern letter can be used here (on all JDK versions).
- * - *In addition, the pattern {@code 'ZZ'} has been made to represent - * ISO8601 full format time zones (eg. {@code +08:00} or {@code -11:00}). - * This introduces a minor incompatibility with Java 1.4, but at a gain of - * useful functionality.
- * - *Javadoc cites for the year pattern: For formatting, if the number of - * pattern letters is 2, the year is truncated to 2 digits; otherwise it is - * interpreted as a number. Starting with Java 1.7 a pattern of 'Y' or - * 'YYY' will be formatted as '2003', while it was '03' in former Java - * versions. FastDateFormat implements the behavior of Java 7.
- * - * @since 2.0 - * @version $Id: FastDateFormat.java 1146138 2011-07-13 17:01:37Z joehni $ - */ -public class FastDateFormat extends Format { - // A lot of the speed in this class comes from caching, but some comes - // from the special int to StringBuffer conversion. - // - // The following produces a padded 2 digit number: - // buffer.append((char)(value / 10 + '0')); - // buffer.append((char)(value % 10 + '0')); - // - // Note that the fastest append to StringBuffer is a single char (used here). - // Note that Integer.toString() is not called, the conversion is simply - // taking the value and adding (mathematically) the ASCII value for '0'. - // So, don't change this code! It works and is very fast. - - /** - * Required for serialization support. - * - * @see java.io.Serializable - */ - private static final long serialVersionUID = 1L; - - /** - * FULL locale dependent date or time style. - */ - public static final int FULL = DateFormat.FULL; - /** - * LONG locale dependent date or time style. - */ - public static final int LONG = DateFormat.LONG; - /** - * MEDIUM locale dependent date or time style. - */ - public static final int MEDIUM = DateFormat.MEDIUM; - /** - * SHORT locale dependent date or time style. - */ - public static final int SHORT = DateFormat.SHORT; - - private static final FormatCacheGets a formatter instance using the default pattern in the - * default locale.
- * - * @return a date/time formatter - */ - public static FastDateFormat getInstance() { - return cache.getDateTimeInstance(SHORT, SHORT, null, null); - } - - /** - *Gets a formatter instance using the specified pattern in the - * default locale.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible - * pattern - * @return a pattern based date/time formatter - * @throws IllegalArgumentException if pattern is invalid - */ - public static FastDateFormat getInstance(String pattern) { - return cache.getInstance(pattern, null, null); - } - - /** - *Gets a formatter instance using the specified pattern and - * time zone.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible - * pattern - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @return a pattern based date/time formatter - * @throws IllegalArgumentException if pattern is invalid - */ - public static FastDateFormat getInstance(String pattern, TimeZone timeZone) { - return cache.getInstance(pattern, timeZone, null); - } - - /** - *Gets a formatter instance using the specified pattern and - * locale.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible - * pattern - * @param locale optional locale, overrides system locale - * @return a pattern based date/time formatter - * @throws IllegalArgumentException if pattern is invalid - */ - public static FastDateFormat getInstance(String pattern, Locale locale) { - return cache.getInstance(pattern, null, locale); - } - - /** - *Gets a formatter instance using the specified pattern, time zone - * and locale.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible - * pattern - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @param locale optional locale, overrides system locale - * @return a pattern based date/time formatter - * @throws IllegalArgumentException if pattern is invalid - * or {@code null} - */ - public static FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale) { - return cache.getInstance(pattern, timeZone, locale); - } - - //----------------------------------------------------------------------- - /** - *Gets a date formatter instance using the specified style in the - * default time zone and locale.
- * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @return a localized standard date formatter - * @throws IllegalArgumentException if the Locale has no date - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getDateInstance(int style) { - return cache.getDateTimeInstance(style, null, null, null); - } - - /** - *Gets a date formatter instance using the specified style and - * locale in the default time zone.
- * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @param locale optional locale, overrides system locale - * @return a localized standard date formatter - * @throws IllegalArgumentException if the Locale has no date - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getDateInstance(int style, Locale locale) { - return cache.getDateTimeInstance(style, null, null, locale); - } - - /** - *Gets a date formatter instance using the specified style and - * time zone in the default locale.
- * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @return a localized standard date formatter - * @throws IllegalArgumentException if the Locale has no date - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getDateInstance(int style, TimeZone timeZone) { - return cache.getDateTimeInstance(style, null, timeZone, null); - } - - /** - *Gets a date formatter instance using the specified style, time - * zone and locale.
- * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @param locale optional locale, overrides system locale - * @return a localized standard date formatter - * @throws IllegalArgumentException if the Locale has no date - * pattern defined - */ - public static FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale) { - return cache.getDateTimeInstance(style, null, timeZone, locale); - } - - //----------------------------------------------------------------------- - /** - *Gets a time formatter instance using the specified style in the - * default time zone and locale.
- * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @return a localized standard time formatter - * @throws IllegalArgumentException if the Locale has no time - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getTimeInstance(int style) { - return cache.getDateTimeInstance(null, style, null, null); - } - - /** - *Gets a time formatter instance using the specified style and - * locale in the default time zone.
- * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @param locale optional locale, overrides system locale - * @return a localized standard time formatter - * @throws IllegalArgumentException if the Locale has no time - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getTimeInstance(int style, Locale locale) { - return cache.getDateTimeInstance(null, style, null, locale); - } - - /** - *Gets a time formatter instance using the specified style and - * time zone in the default locale.
- * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted time - * @return a localized standard time formatter - * @throws IllegalArgumentException if the Locale has no time - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getTimeInstance(int style, TimeZone timeZone) { - return cache.getDateTimeInstance(null, style, timeZone, null); - } - - /** - *Gets a time formatter instance using the specified style, time - * zone and locale.
- * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted time - * @param locale optional locale, overrides system locale - * @return a localized standard time formatter - * @throws IllegalArgumentException if the Locale has no time - * pattern defined - */ - public static FastDateFormat getTimeInstance(int style, TimeZone timeZone, Locale locale) { - return cache.getDateTimeInstance(null, style, timeZone, locale); - } - - //----------------------------------------------------------------------- - /** - *Gets a date/time formatter instance using the specified style - * in the default time zone and locale.
- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle) { - return cache.getDateTimeInstance(dateStyle, timeStyle, null, null); - } - - /** - *Gets a date/time formatter instance using the specified style and - * locale in the default time zone.
- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) { - return cache.getDateTimeInstance(dateStyle, timeStyle, null, locale); - } - - /** - *Gets a date/time formatter instance using the specified style and - * time zone in the default locale.
- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time - * pattern defined - * @since 2.1 - */ - public static FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone) { - return getDateTimeInstance(dateStyle, timeStyle, timeZone, null); - } - /** - *Gets a date/time formatter instance using the specified style, - * time zone and locale.
- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time - * pattern defined - */ - public static FastDateFormat getDateTimeInstance( - int dateStyle, int timeStyle, TimeZone timeZone, Locale locale) { - return cache.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale); - } - - //----------------------------------------------------------------------- - /** - *Gets the time zone display name, using a cache for performance.
- * - * @param tz the zone to query - * @param daylight true if daylight savings - * @param style the style to use {@code TimeZone.LONG} or {@code TimeZone.SHORT} - * @param locale the locale to use - * @return the textual name of the time zone - */ - static String getTimeZoneDisplay(TimeZone tz, boolean daylight, int style, Locale locale) { - TimeZoneDisplayKey key = new TimeZoneDisplayKey(tz, daylight, style, locale); - String value = cTimeZoneDisplayCache.get(key); - if (value == null) { - // This is a very slow call, so cache the results. - value = tz.getDisplayName(daylight, style, locale); - String prior = cTimeZoneDisplayCache.putIfAbsent(key, value); - if (prior != null) { - value= prior; - } - } - return value; - } - - // Constructor - //----------------------------------------------------------------------- - /** - *Constructs a new FastDateFormat.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible pattern - * @param timeZone non-null time zone to use - * @param locale non-null locale to use - * @throws NullPointerException if pattern, timeZone, or locale is null. - */ - protected FastDateFormat(String pattern, TimeZone timeZone, Locale locale) { - mPattern = pattern; - mTimeZone = timeZone; - mLocale = locale; - - init(); - } - - /** - *Initializes the instance for first use.
- */ - private void init() { - ListReturns a list of Rules given a pattern.
- * - * @return a {@code List} of Rule objects - * @throws IllegalArgumentException if pattern is invalid - */ - protected ListPerforms the parsing of tokens.
- * - * @param pattern the pattern - * @param indexRef index references - * @return parsed token - */ - protected String parseToken(String pattern, int[] indexRef) { - StringBuilder buf = new StringBuilder(); - - int i = indexRef[0]; - int length = pattern.length(); - - char c = pattern.charAt(i); - if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { - // Scan a run of the same character, which indicates a time - // pattern. - buf.append(c); - - while (i + 1 < length) { - char peek = pattern.charAt(i + 1); - if (peek == c) { - buf.append(c); - i++; - } else { - break; - } - } - } else { - // This will identify token as text. - buf.append('\''); - - boolean inLiteral = false; - - for (; i < length; i++) { - c = pattern.charAt(i); - - if (c == '\'') { - if (i + 1 < length && pattern.charAt(i + 1) == '\'') { - // '' is treated as escaped ' - i++; - buf.append(c); - } else { - inLiteral = !inLiteral; - } - } else if (!inLiteral && - (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) { - i--; - break; - } else { - buf.append(c); - } - } - } - - indexRef[0] = i; - return buf.toString(); - } - - /** - *Gets an appropriate rule for the padding required.
- * - * @param field the field to get a rule for - * @param padding the padding required - * @return a new rule with the correct padding - */ - protected NumberRule selectNumberRule(int field, int padding) { - switch (padding) { - case 1: - return new UnpaddedNumberField(field); - case 2: - return new TwoDigitNumberField(field); - default: - return new PaddedNumberField(field, padding); - } - } - - // Format methods - //----------------------------------------------------------------------- - /** - *Formats a {@code Date}, {@code Calendar} or - * {@code Long} (milliseconds) object.
- * - * @param obj the object to format - * @param toAppendTo the buffer to append to - * @param pos the position - ignored - * @return the buffer passed in - */ - @Override - public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { - if (obj instanceof Date) { - return format((Date) obj, toAppendTo); - } else if (obj instanceof Calendar) { - return format((Calendar) obj, toAppendTo); - } else if (obj instanceof Long) { - return format(((Long) obj).longValue(), toAppendTo); - } else { - throw new IllegalArgumentException("Unknown class: " + - (obj == null ? "Formats a millisecond {@code long} value.
- * - * @param millis the millisecond value to format - * @return the formatted string - * @since 2.1 - */ - public String format(long millis) { - return format(new Date(millis)); - } - - /** - *Formats a {@code Date} object using a {@code GregorianCalendar}.
- * - * @param date the date to format - * @return the formatted string - */ - public String format(Date date) { - Calendar c = new GregorianCalendar(mTimeZone, mLocale); // hard code GregorianCalendar - c.setTime(date); - return applyRules(c, new StringBuffer(mMaxLengthEstimate)).toString(); - } - - /** - *Formats a {@code Calendar} object.
- * - * @param calendar the calendar to format - * @return the formatted string - */ - public String format(Calendar calendar) { - return format(calendar, new StringBuffer(mMaxLengthEstimate)).toString(); - } - - /** - *Formats a milliseond {@code long} value into the - * supplied {@code StringBuffer}.
- * - * @param millis the millisecond value to format - * @param buf the buffer to format into - * @return the specified string buffer - * @since 2.1 - */ - public StringBuffer format(long millis, StringBuffer buf) { - return format(new Date(millis), buf); - } - - /** - *Formats a {@code Date} object into the - * supplied {@code StringBuffer} using a {@code GregorianCalendar}.
- * - * @param date the date to format - * @param buf the buffer to format into - * @return the specified string buffer - */ - public StringBuffer format(Date date, StringBuffer buf) { - Calendar c = new GregorianCalendar(mTimeZone, mLocale); // hard code GregorianCalendar - c.setTime(date); - return applyRules(c, buf); - } - - /** - *Formats a {@code Calendar} object into the - * supplied {@code StringBuffer}.
- * - * @param calendar the calendar to format - * @param buf the buffer to format into - * @return the specified string buffer - */ - public StringBuffer format(Calendar calendar, StringBuffer buf) { - return applyRules(calendar, buf); - } - - /** - *Performs the formatting by applying the rules to the - * specified calendar.
- * - * @param calendar the calendar to format - * @param buf the buffer to format into - * @return the specified string buffer - */ - protected StringBuffer applyRules(Calendar calendar, StringBuffer buf) { - for (Rule rule : mRules) { - rule.appendTo(buf, calendar); - } - return buf; - } - - // Parsing - //----------------------------------------------------------------------- - /** - *Parsing is not supported.
- * - * @param source the string to parse - * @param pos the parsing position - * @return {@code null} as not supported - */ - @Override - public Object parseObject(String source, ParsePosition pos) { - pos.setIndex(0); - pos.setErrorIndex(0); - return null; - } - - // Accessors - //----------------------------------------------------------------------- - /** - *Gets the pattern used by this formatter.
- * - * @return the pattern, {@link java.text.SimpleDateFormat} compatible - */ - public String getPattern() { - return mPattern; - } - - /** - *Gets the time zone used by this formatter.
- * - *This zone is always used for {@code Date} formatting.
- * - * @return the time zone - */ - public TimeZone getTimeZone() { - return mTimeZone; - } - - /** - *Gets the locale used by this formatter.
- * - * @return the locale - */ - public Locale getLocale() { - return mLocale; - } - - /** - *Gets an estimate for the maximum string length that the - * formatter will produce.
- * - *The actual formatted length will almost always be less than or - * equal to this amount.
- * - * @return the maximum formatted length - */ - public int getMaxLengthEstimate() { - return mMaxLengthEstimate; - } - - // Basics - //----------------------------------------------------------------------- - /** - *Compares two objects for equality.
- * - * @param obj the object to compare to - * @return {@code true} if equal - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof FastDateFormat == false) { - return false; - } - FastDateFormat other = (FastDateFormat) obj; - return mPattern.equals(other.mPattern) - && mTimeZone.equals(other.mTimeZone) - && mLocale.equals(other.mLocale); - } - - /** - *Returns a hashcode compatible with equals.
- * - * @return a hashcode compatible with equals - */ - @Override - public int hashCode() { - return mPattern.hashCode() + 13 * (mTimeZone.hashCode() + 13 * mLocale.hashCode()); - } - - /** - *Gets a debugging string version of this formatter.
- * - * @return a debugging string - */ - @Override - public String toString() { - return "FastDateFormat[" + mPattern + "]"; - } - - // Serializing - //----------------------------------------------------------------------- - /** - * Create the object after serialization. This implementation reinitializes the - * transient properties. - * - * @param in ObjectInputStream from which the object is being deserialized. - * @throws IOException if there is an IO issue. - * @throws ClassNotFoundException if a class cannot be found. - */ - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - init(); - } - - // Rules - //----------------------------------------------------------------------- - /** - *Inner class defining a rule.
- */ - private interface Rule { - /** - * Returns the estimated lentgh of the result. - * - * @return the estimated length - */ - int estimateLength(); - - /** - * Appends the value of the specified calendar to the output buffer based on the rule implementation. - * - * @param buffer the output buffer - * @param calendar calendar to be appended - */ - void appendTo(StringBuffer buffer, Calendar calendar); - } - - /** - *Inner class defining a numeric rule.
- */ - private interface NumberRule extends Rule { - /** - * Appends the specified value to the output buffer based on the rule implementation. - * - * @param buffer the output buffer - * @param value the value to be appended - */ - void appendTo(StringBuffer buffer, int value); - } - - /** - *Inner class to output a constant single character.
- */ - private static class CharacterLiteral implements Rule { - private final char mValue; - - /** - * Constructs a new instance of {@code CharacterLiteral} - * to hold the specified value. - * - * @param value the character literal - */ - CharacterLiteral(char value) { - mValue = value; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 1; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - buffer.append(mValue); - } - } - - /** - *Inner class to output a constant string.
- */ - private static class StringLiteral implements Rule { - private final String mValue; - - /** - * Constructs a new instance of {@code StringLiteral} - * to hold the specified value. - * - * @param value the string literal - */ - StringLiteral(String value) { - mValue = value; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return mValue.length(); - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - buffer.append(mValue); - } - } - - /** - *Inner class to output one of a set of values.
- */ - private static class TextField implements Rule { - private final int mField; - private final String[] mValues; - - /** - * Constructs an instance of {@code TextField} - * with the specified field and values. - * - * @param field the field - * @param values the field values - */ - TextField(int field, String[] values) { - mField = field; - mValues = values; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - int max = 0; - for (int i=mValues.length; --i >= 0; ) { - int len = mValues[i].length(); - if (len > max) { - max = len; - } - } - return max; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - buffer.append(mValues[calendar.get(mField)]); - } - } - - /** - *Inner class to output an unpadded number.
- */ - private static class UnpaddedNumberField implements NumberRule { - private final int mField; - - /** - * Constructs an instance of {@code UnpadedNumberField} with the specified field. - * - * @param field the field - */ - UnpaddedNumberField(int field) { - mField = field; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 4; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - appendTo(buffer, calendar.get(mField)); - } - - /** - * {@inheritDoc} - */ - public final void appendTo(StringBuffer buffer, int value) { - if (value < 10) { - buffer.append((char)(value + '0')); - } else if (value < 100) { - buffer.append((char)(value / 10 + '0')); - buffer.append((char)(value % 10 + '0')); - } else { - buffer.append(Integer.toString(value)); - } - } - } - - /** - *Inner class to output an unpadded month.
- */ - private static class UnpaddedMonthField implements NumberRule { - static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField(); - - /** - * Constructs an instance of {@code UnpaddedMonthField}. - * - */ - UnpaddedMonthField() { - super(); - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - appendTo(buffer, calendar.get(Calendar.MONTH) + 1); - } - - /** - * {@inheritDoc} - */ - public final void appendTo(StringBuffer buffer, int value) { - if (value < 10) { - buffer.append((char)(value + '0')); - } else { - buffer.append((char)(value / 10 + '0')); - buffer.append((char)(value % 10 + '0')); - } - } - } - - /** - *Inner class to output a padded number.
- */ - private static class PaddedNumberField implements NumberRule { - private final int mField; - private final int mSize; - - /** - * Constructs an instance of {@code PaddedNumberField}. - * - * @param field the field - * @param size size of the output field - */ - PaddedNumberField(int field, int size) { - if (size < 3) { - // Should use UnpaddedNumberField or TwoDigitNumberField. - throw new IllegalArgumentException(); - } - mField = field; - mSize = size; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 4; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - appendTo(buffer, calendar.get(mField)); - } - - /** - * {@inheritDoc} - */ - public final void appendTo(StringBuffer buffer, int value) { - if (value < 100) { - for (int i = mSize; --i >= 2; ) { - buffer.append('0'); - } - buffer.append((char)(value / 10 + '0')); - buffer.append((char)(value % 10 + '0')); - } else { - int digits; - if (value < 1000) { - digits = 3; - } else { - Validate.isTrue(value > -1, "Negative values should not be possible", value); - digits = Integer.toString(value).length(); - } - for (int i = mSize; --i >= digits; ) { - buffer.append('0'); - } - buffer.append(Integer.toString(value)); - } - } - } - - /** - *Inner class to output a two digit number.
- */ - private static class TwoDigitNumberField implements NumberRule { - private final int mField; - - /** - * Constructs an instance of {@code TwoDigitNumberField} with the specified field. - * - * @param field the field - */ - TwoDigitNumberField(int field) { - mField = field; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - appendTo(buffer, calendar.get(mField)); - } - - /** - * {@inheritDoc} - */ - public final void appendTo(StringBuffer buffer, int value) { - if (value < 100) { - buffer.append((char)(value / 10 + '0')); - buffer.append((char)(value % 10 + '0')); - } else { - buffer.append(Integer.toString(value)); - } - } - } - - /** - *Inner class to output a two digit year.
- */ - private static class TwoDigitYearField implements NumberRule { - static final TwoDigitYearField INSTANCE = new TwoDigitYearField(); - - /** - * Constructs an instance of {@code TwoDigitYearField}. - */ - TwoDigitYearField() { - super(); - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - appendTo(buffer, calendar.get(Calendar.YEAR) % 100); - } - - /** - * {@inheritDoc} - */ - public final void appendTo(StringBuffer buffer, int value) { - buffer.append((char)(value / 10 + '0')); - buffer.append((char)(value % 10 + '0')); - } - } - - /** - *Inner class to output a two digit month.
- */ - private static class TwoDigitMonthField implements NumberRule { - static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField(); - - /** - * Constructs an instance of {@code TwoDigitMonthField}. - */ - TwoDigitMonthField() { - super(); - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - appendTo(buffer, calendar.get(Calendar.MONTH) + 1); - } - - /** - * {@inheritDoc} - */ - public final void appendTo(StringBuffer buffer, int value) { - buffer.append((char)(value / 10 + '0')); - buffer.append((char)(value % 10 + '0')); - } - } - - /** - *Inner class to output the twelve hour field.
- */ - private static class TwelveHourField implements NumberRule { - private final NumberRule mRule; - - /** - * Constructs an instance of {@code TwelveHourField} with the specified - * {@code NumberRule}. - * - * @param rule the rule - */ - TwelveHourField(NumberRule rule) { - mRule = rule; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return mRule.estimateLength(); - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - int value = calendar.get(Calendar.HOUR); - if (value == 0) { - value = calendar.getLeastMaximum(Calendar.HOUR) + 1; - } - mRule.appendTo(buffer, value); - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, int value) { - mRule.appendTo(buffer, value); - } - } - - /** - *Inner class to output the twenty four hour field.
- */ - private static class TwentyFourHourField implements NumberRule { - private final NumberRule mRule; - - /** - * Constructs an instance of {@code TwentyFourHourField} with the specified - * {@code NumberRule}. - * - * @param rule the rule - */ - TwentyFourHourField(NumberRule rule) { - mRule = rule; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return mRule.estimateLength(); - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - int value = calendar.get(Calendar.HOUR_OF_DAY); - if (value == 0) { - value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1; - } - mRule.appendTo(buffer, value); - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, int value) { - mRule.appendTo(buffer, value); - } - } - - /** - *Inner class to output a time zone name.
- */ - private static class TimeZoneNameRule implements Rule { - private final TimeZone mTimeZone; - private final String mStandard; - private final String mDaylight; - - /** - * Constructs an instance of {@code TimeZoneNameRule} with the specified properties. - * - * @param timeZone the time zone - * @param locale the locale - * @param style the style - */ - TimeZoneNameRule(TimeZone timeZone, Locale locale, int style) { - mTimeZone = timeZone; - - mStandard = getTimeZoneDisplay(timeZone, false, style, locale); - mDaylight = getTimeZoneDisplay(timeZone, true, style, locale); - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return Math.max(mStandard.length(), mDaylight.length()); - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - if (mTimeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) { - buffer.append(mDaylight); - } else { - buffer.append(mStandard); - } - } - } - - /** - *Inner class to output a time zone as a number {@code +/-HHMM} - * or {@code +/-HH:MM}.
- */ - private static class TimeZoneNumberRule implements Rule { - static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true); - static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false); - - final boolean mColon; - - /** - * Constructs an instance of {@code TimeZoneNumberRule} with the specified properties. - * - * @param colon add colon between HH and MM in the output if {@code true} - */ - TimeZoneNumberRule(boolean colon) { - mColon = colon; - } - - /** - * {@inheritDoc} - */ - public int estimateLength() { - return 5; - } - - /** - * {@inheritDoc} - */ - public void appendTo(StringBuffer buffer, Calendar calendar) { - int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); - - if (offset < 0) { - buffer.append('-'); - offset = -offset; - } else { - buffer.append('+'); - } - - int hours = offset / (60 * 60 * 1000); - buffer.append((char)(hours / 10 + '0')); - buffer.append((char)(hours % 10 + '0')); - - if (mColon) { - buffer.append(':'); - } - - int minutes = offset / (60 * 1000) - 60 * hours; - buffer.append((char)(minutes / 10 + '0')); - buffer.append((char)(minutes % 10 + '0')); - } - } - - // ---------------------------------------------------------------------- - /** - *Inner class that acts as a compound key for time zone names.
- */ - private static class TimeZoneDisplayKey { - private final TimeZone mTimeZone; - private final int mStyle; - private final Locale mLocale; - - /** - * Constructs an instance of {@code TimeZoneDisplayKey} with the specified properties. - * - * @param timeZone the time zone - * @param daylight adjust the style for daylight saving time if {@code true} - * @param style the timezone style - * @param locale the timezone locale - */ - TimeZoneDisplayKey(TimeZone timeZone, - boolean daylight, int style, Locale locale) { - mTimeZone = timeZone; - if (daylight) { - style |= 0x80000000; - } - mStyle = style; - mLocale = locale; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - return (mStyle * 31 + mLocale.hashCode() ) * 31 + mTimeZone.hashCode(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof TimeZoneDisplayKey) { - TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj; - return - mTimeZone.equals(other.mTimeZone) && - mStyle == other.mStyle && - mLocale.equals(other.mLocale); - } - return false; - } - } -} diff --git a/src/org/apache/commons/lang3/time/FormatCache.java b/src/org/apache/commons/lang3/time/FormatCache.java deleted file mode 100644 index 19ee53a..0000000 --- a/src/org/apache/commons/lang3/time/FormatCache.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * 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.commons.lang3.time; - -import java.text.DateFormat; -import java.text.Format; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Locale; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - *FormatCache is a cache and factory for {@link Format}s.
- * - * @since 3.0 - * @version $Id: FormatCache 892161 2009-12-18 07:21:10Z $ - */ -// TODO: Before making public move from getDateTimeInstance(Integer,...) to int; or some other approach. -abstract class FormatCacheGets a formatter instance using the default pattern in the - * default timezone and locale.
- * - * @return a date/time formatter - */ - public F getInstance() { - return getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, TimeZone.getDefault(), Locale.getDefault()); - } - - /** - *Gets a formatter instance using the specified pattern, time zone - * and locale.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible - * pattern - * @param timeZone the non-null time zone - * @param locale the non-null locale - * @return a pattern based date/time formatter - * @throws IllegalArgumentException if pattern is invalid - * ornull
- */
- public F getInstance(String pattern, TimeZone timeZone, Locale locale) {
- if (pattern == null) {
- throw new NullPointerException("pattern must not be null");
- }
- if (timeZone == null) {
- timeZone = TimeZone.getDefault();
- }
- if (locale == null) {
- locale = Locale.getDefault();
- }
- MultipartKey key = new MultipartKey(pattern, timeZone, locale);
- F format = cInstanceCache.get(key);
- if (format == null) {
- format = createInstance(pattern, timeZone, locale);
- F previousValue= cInstanceCache.putIfAbsent(key, format);
- if (previousValue != null) {
- // another thread snuck in and did the same work
- // we should return the instance that is in ConcurrentMap
- format= previousValue;
- }
- }
- return format;
- }
-
- /**
- * Create a format instance using the specified pattern, time zone - * and locale.
- * - * @param pattern {@link java.text.SimpleDateFormat} compatible pattern, this will not be null. - * @param timeZone time zone, this will not be null. - * @param locale locale, this will not be null. - * @return a pattern based date/time formatter - * @throws IllegalArgumentException if pattern is invalid - * ornull
- */
- abstract protected F createInstance(String pattern, TimeZone timeZone, Locale locale);
-
- /**
- * Gets a date/time formatter instance using the specified style, - * time zone and locale.
- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of - * formatted date - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time - * pattern defined - */ - public F getDateTimeInstance(Integer dateStyle, Integer timeStyle, TimeZone timeZone, Locale locale) { - if (locale == null) { - locale = Locale.getDefault(); - } - MultipartKey key = new MultipartKey(dateStyle, timeStyle, locale); - - String pattern = cDateTimeInstanceCache.get(key); - if (pattern == null) { - try { - DateFormat formatter; - if (dateStyle == null) { - formatter = DateFormat.getTimeInstance(timeStyle, locale); - } - else if (timeStyle == null) { - formatter = DateFormat.getDateInstance(dateStyle, locale); - } - else { - formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); - } - pattern = ((SimpleDateFormat)formatter).toPattern(); - String previous = cDateTimeInstanceCache.putIfAbsent(key, pattern); - if (previous != null) { - // even though it doesn't matter if another thread put the pattern - // it's still good practice to return the String instance that is - // actually in the ConcurrentMap - pattern= previous; - } - } catch (ClassCastException ex) { - throw new IllegalArgumentException("No date time pattern for locale: " + locale); - } - } - - return getInstance(pattern, timeZone, locale); - } - - // ---------------------------------------------------------------------- - /** - *Helper class to hold multi-part Map keys
- */ - private static class MultipartKey { - private final Object[] keys; - private int hashCode; - - /** - * Constructs an instance ofMultipartKey to hold the specified objects.
- * @param keys the set of objects that make up the key. Each key may be null.
- */
- public MultipartKey(Object... keys) {
- this.keys = keys;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if ( obj instanceof MultipartKey == false ) {
- return false;
- }
- return Arrays.equals(keys, ((MultipartKey)obj).keys);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- if(hashCode==0) {
- int rc= 0;
- for(Object key : keys) {
- if(key!=null) {
- rc= rc*7 + key.hashCode();
- }
- }
- hashCode= rc;
- }
- return hashCode;
- }
- }
-
-}
diff --git a/src/org/apache/commons/lang3/time/StopWatch.java b/src/org/apache/commons/lang3/time/StopWatch.java
deleted file mode 100644
index f86ad85..0000000
--- a/src/org/apache/commons/lang3/time/StopWatch.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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.commons.lang3.time;
-
-/**
- *
- * StopWatch provides a convenient API for timings.
- *
- * To start the watch, call {@link #start()}. At this point you can: - *
- *- * It is intended that the output methods {@link #toString()} and {@link #getTime()} should only be called after stop, - * split or suspend, however a suitable result will be returned at other points. - *
- * - *- * NOTE: As from v2.1, the methods protect against inappropriate calls. Thus you cannot now call stop before start, - * resume before suspend or unsplit before split. - *
- * - *
- * 1. split(), suspend(), or stop() cannot be invoked twice
- * 2. unsplit() may only be called if the watch has been split()
- * 3. resume() may only be called if the watch has been suspend()
- * 4. start() cannot be called twice without calling reset()
- *
This class is not thread-safe
- * - * @since 2.0 - * @version $Id: StopWatch.java 1088899 2011-04-05 05:31:27Z bayard $ - */ -public class StopWatch { - - private static final long NANO_2_MILLIS = 1000000L; - - // running states - private static final int STATE_UNSTARTED = 0; - - private static final int STATE_RUNNING = 1; - - private static final int STATE_STOPPED = 2; - - private static final int STATE_SUSPENDED = 3; - - // split state - private static final int STATE_UNSPLIT = 10; - - private static final int STATE_SPLIT = 11; - - /** - * The current running state of the StopWatch. - */ - private int runningState = STATE_UNSTARTED; - - /** - * Whether the stopwatch has a split time recorded. - */ - private int splitState = STATE_UNSPLIT; - - /** - * The start time. - */ - private long startTime; - - /** - * The start time in Millis - nanoTime is only for elapsed time so we - * need to also store the currentTimeMillis to maintain the old - * getStartTime API. - */ - private long startTimeMillis; - - /** - * The stop time. - */ - private long stopTime; - - /** - *- * Constructor. - *
- */ - public StopWatch() { - super(); - } - - /** - *- * Start the stopwatch. - *
- * - *- * This method starts a new timing session, clearing any previous values. - *
- * - * @throws IllegalStateException - * if the StopWatch is already running. - */ - public void start() { - if (this.runningState == STATE_STOPPED) { - throw new IllegalStateException("Stopwatch must be reset before being restarted. "); - } - if (this.runningState != STATE_UNSTARTED) { - throw new IllegalStateException("Stopwatch already started. "); - } - this.startTime = System.nanoTime(); - this.startTimeMillis = System.currentTimeMillis(); - this.runningState = STATE_RUNNING; - } - - /** - *- * Stop the stopwatch. - *
- * - *- * This method ends a new timing session, allowing the time to be retrieved. - *
- * - * @throws IllegalStateException - * if the StopWatch is not running. - */ - public void stop() { - if (this.runningState != STATE_RUNNING && this.runningState != STATE_SUSPENDED) { - throw new IllegalStateException("Stopwatch is not running. "); - } - if (this.runningState == STATE_RUNNING) { - this.stopTime = System.nanoTime(); - } - this.runningState = STATE_STOPPED; - } - - /** - *- * Resets the stopwatch. Stops it if need be. - *
- * - *- * This method clears the internal values to allow the object to be reused. - *
- */ - public void reset() { - this.runningState = STATE_UNSTARTED; - this.splitState = STATE_UNSPLIT; - } - - /** - *- * Split the time. - *
- * - *- * This method sets the stop time of the watch to allow a time to be extracted. The start time is unaffected, - * enabling {@link #unsplit()} to continue the timing from the original start point. - *
- * - * @throws IllegalStateException - * if the StopWatch is not running. - */ - public void split() { - if (this.runningState != STATE_RUNNING) { - throw new IllegalStateException("Stopwatch is not running. "); - } - this.stopTime = System.nanoTime(); - this.splitState = STATE_SPLIT; - } - - /** - *- * Remove a split. - *
- * - *- * This method clears the stop time. The start time is unaffected, enabling timing from the original start point to - * continue. - *
- * - * @throws IllegalStateException - * if the StopWatch has not been split. - */ - public void unsplit() { - if (this.splitState != STATE_SPLIT) { - throw new IllegalStateException("Stopwatch has not been split. "); - } - this.splitState = STATE_UNSPLIT; - } - - /** - *- * Suspend the stopwatch for later resumption. - *
- * - *- * This method suspends the watch until it is resumed. The watch will not include time between the suspend and - * resume calls in the total time. - *
- * - * @throws IllegalStateException - * if the StopWatch is not currently running. - */ - public void suspend() { - if (this.runningState != STATE_RUNNING) { - throw new IllegalStateException("Stopwatch must be running to suspend. "); - } - this.stopTime = System.nanoTime(); - this.runningState = STATE_SUSPENDED; - } - - /** - *- * Resume the stopwatch after a suspend. - *
- * - *- * This method resumes the watch after it was suspended. The watch will not include time between the suspend and - * resume calls in the total time. - *
- * - * @throws IllegalStateException - * if the StopWatch has not been suspended. - */ - public void resume() { - if (this.runningState != STATE_SUSPENDED) { - throw new IllegalStateException("Stopwatch must be suspended to resume. "); - } - this.startTime += (System.nanoTime() - this.stopTime); - this.runningState = STATE_RUNNING; - } - - /** - *- * Get the time on the stopwatch. - *
- * - *- * This is either the time between the start and the moment this method is called, or the amount of time between - * start and stop. - *
- * - * @return the time in milliseconds - */ - public long getTime() { - return getNanoTime() / NANO_2_MILLIS; - } - /** - *- * Get the time on the stopwatch in nanoseconds. - *
- * - *- * This is either the time between the start and the moment this method is called, or the amount of time between - * start and stop. - *
- * - * @return the time in nanoseconds - * @since 3.0 - */ - public long getNanoTime() { - if (this.runningState == STATE_STOPPED || this.runningState == STATE_SUSPENDED) { - return this.stopTime - this.startTime; - } else if (this.runningState == STATE_UNSTARTED) { - return 0; - } else if (this.runningState == STATE_RUNNING) { - return System.nanoTime() - this.startTime; - } - throw new RuntimeException("Illegal running state has occured. "); - } - - /** - *- * Get the split time on the stopwatch. - *
- * - *- * This is the time between start and latest split. - *
- * - * @return the split time in milliseconds - * - * @throws IllegalStateException - * if the StopWatch has not yet been split. - * @since 2.1 - */ - public long getSplitTime() { - return getSplitNanoTime() / NANO_2_MILLIS; - } - /** - *- * Get the split time on the stopwatch in nanoseconds. - *
- * - *- * This is the time between start and latest split. - *
- * - * @return the split time in nanoseconds - * - * @throws IllegalStateException - * if the StopWatch has not yet been split. - * @since 3.0 - */ - public long getSplitNanoTime() { - if (this.splitState != STATE_SPLIT) { - throw new IllegalStateException("Stopwatch must be split to get the split time. "); - } - return this.stopTime - this.startTime; - } - - /** - * Returns the time this stopwatch was started. - * - * @return the time this stopwatch was started - * @throws IllegalStateException - * if this StopWatch has not been started - * @since 2.4 - */ - public long getStartTime() { - if (this.runningState == STATE_UNSTARTED) { - throw new IllegalStateException("Stopwatch has not been started"); - } - // System.nanoTime is for elapsed time - return this.startTimeMillis; - } - - /** - *- * Gets a summary of the time that the stopwatch recorded as a string. - *
- * - *- * The format used is ISO8601-like, hours:minutes:seconds.milliseconds. - *
- * - * @return the time as a String - */ - @Override - public String toString() { - return DurationFormatUtils.formatDurationHMS(getTime()); - } - - /** - *- * Gets a summary of the split time that the stopwatch recorded as a string. - *
- * - *- * The format used is ISO8601-like, hours:minutes:seconds.milliseconds. - *
- * - * @return the split time as a String - * @since 2.1 - */ - public String toSplitString() { - return DurationFormatUtils.formatDurationHMS(getSplitTime()); - } - -} -- cgit v1.1