You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by ad...@apache.org on 2019/05/06 13:01:09 UTC
[wicket] branch WICKET-6662 updated: Reintroduced deprecated
classes from package org.apache.wicket.util.time
This is an automated email from the ASF dual-hosted git repository.
adelbene pushed a commit to branch WICKET-6662
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/WICKET-6662 by this push:
new a0dd2df Reintroduced deprecated classes from package org.apache.wicket.util.time
a0dd2df is described below
commit a0dd2df5fa04a4ec8727ce17e25c34b1f5a4d4cb
Author: Andrea Del Bene <an...@gmail.com>
AuthorDate: Mon May 6 13:10:30 2019 +0200
Reintroduced deprecated classes from package org.apache.wicket.util.time
---
.../org/apache/wicket/util/time/AbstractTime.java | 121 ++++
.../apache/wicket/util/time/AbstractTimeValue.java | 54 ++
.../java/org/apache/wicket/util/time/Duration.java | 554 +++++++++++++++++++
.../apache/wicket/util/time/ITimeFrameSource.java | 40 ++
.../java/org/apache/wicket/util/time/Time.java | 614 +++++++++++++++++++++
.../org/apache/wicket/util/time/TimeFrame.java | 260 +++++++++
.../java/org/apache/wicket/util/time/TimeMap.java | 110 ++++
.../org/apache/wicket/util/time/TimeOfDay.java | 419 ++++++++++++++
8 files changed, 2172 insertions(+)
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/AbstractTime.java b/wicket-util/src/main/java/org/apache/wicket/util/time/AbstractTime.java
new file mode 100755
index 0000000..01d2f42
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/AbstractTime.java
@@ -0,0 +1,121 @@
+/*
+ * 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.wicket.util.time;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Abstract base class for subclasses that represent a point in time (as opposed to a
+ * {@link Duration} of time).
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+abstract class AbstractTime extends AbstractTimeValue
+{
+ private static final long serialVersionUID = 1L;
+
+ /** calendar for the local time zone */
+ static final Calendar localtime = Calendar.getInstance();
+
+ /** time format */
+ static final SimpleDateFormat timeFormat = new SimpleDateFormat("h.mma", Locale.ENGLISH);
+
+ /**
+ * @param milliseconds
+ * @see AbstractTimeValue
+ */
+ AbstractTime(final long milliseconds)
+ {
+ super(milliseconds);
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Time</code> value is after the given
+ * <code>Time</code> argument's value.
+ *
+ * @param that
+ * the <code>AbstractTimeValue</code> to compare with
+ * @return <code>true</code> if this <code>Time</code> value is after <code>that</code>
+ * <code>Time</code> value
+ */
+ public final boolean after(final AbstractTimeValue that)
+ {
+ return greaterThan(that);
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Time</code> value is before the given
+ * <code>Time</code> argument's value.
+ *
+ * @param that
+ * the <code>AbstractTimeValue</code> to compare with
+ * @return <code>true</code> if this <code>Time</code> value is before <code>that</code>
+ * <code>Time</code> value
+ */
+ public final boolean before(final AbstractTimeValue that)
+ {
+ return lessThan(that);
+ }
+
+ /**
+ * Converts this <code>Time</code> to a time <code>String</code> using the formatter 'h.mma'.
+ *
+ * @return the <code>Time</code> <code>String</code>
+ */
+ public final String toTimeString()
+ {
+ return toTimeString(localtime);
+ }
+
+ /**
+ * Converts this <code>Time</code> to a <code>Date String</code> using the <code>Date</code>
+ * formatter 'h.mma'.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use in the conversion
+ * @return the <code>Date</code> <code>String</code>
+ */
+ public final String toTimeString(final Calendar calendar)
+ {
+ synchronized (timeFormat)
+ {
+ synchronized (calendar)
+ {
+ timeFormat.setCalendar(calendar);
+ return timeFormat.format(new Date(getMilliseconds())).toLowerCase(Locale.ROOT);
+ }
+ }
+ }
+
+ /**
+ * Converts this <code>Time</code> to a <code>String</code> suitable for use in a file system
+ * name.
+ *
+ * @return this <code>Time</code> as a formatted <code>String</code>
+ */
+ @Override
+ public String toString()
+ {
+ return toTimeString();
+ }
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/AbstractTimeValue.java b/wicket-util/src/main/java/org/apache/wicket/util/time/AbstractTimeValue.java
new file mode 100755
index 0000000..d1bc813
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/AbstractTimeValue.java
@@ -0,0 +1,54 @@
+/*
+ * 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.wicket.util.time;
+
+import org.apache.wicket.util.value.LongValue;
+
+/**
+ * Package local class for representing immutable time values in milliseconds and typical operations
+ * on such values.
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+abstract class AbstractTimeValue extends LongValue
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Package local constructor for package subclasses only.
+ *
+ * @param milliseconds
+ * the number of milliseconds in this <code>Time</code> value
+ */
+ AbstractTimeValue(final long milliseconds)
+ {
+ super(milliseconds);
+ }
+
+ /**
+ * Retrieves the number of milliseconds in this <code>Time</code> value.
+ *
+ * @return the number of milliseconds in this <code>Time</code> value
+ */
+ public final long getMilliseconds()
+ {
+ return value;
+ }
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/Duration.java b/wicket-util/src/main/java/org/apache/wicket/util/time/Duration.java
new file mode 100755
index 0000000..2b5345c
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/Duration.java
@@ -0,0 +1,554 @@
+/*
+ * 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.wicket.util.time;
+
+import java.util.Locale;
+import java.util.Locale.Category;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.wicket.util.string.StringValue;
+import org.apache.wicket.util.string.StringValueConversionException;
+import org.apache.wicket.util.thread.ICode;
+import org.slf4j.Logger;
+
+
+/**
+ * A <code>Duration</code> is an immutable length of time stored as a number of milliseconds.
+ * Various factory and conversion methods are available for convenience.
+ * <p>
+ * These static factory methods allow easy construction of value objects using either long values
+ * like <code>seconds(2034)</code> or <code>hours(3)</code>:
+ * <p>
+ * <ul>
+ * <li><code>Duration.milliseconds(long)</code>
+ * <li><code>Duration.seconds(int)</code>
+ * <li><code>Duration.minutes(int)</code>
+ * <li><code>Duration.hours(int)</code>
+ * <li><code>Duration.days(int)</code>
+ * </ul>
+ * <p>
+ * ...or double-precision floating point values like <code>days(3.2)</code>:
+ * <p>
+ * <ul>
+ * <li><code>Duration.milliseconds(double)</code>
+ * <li><code>Duration.seconds(double)</code>
+ * <li><code>Duration.minutes(double)</code>
+ * <li><code>Duration.hours(double)</code>
+ * <li><code>Duration.days(double)</code>
+ * </ul>
+ * <p>
+ * In the case of <code>milliseconds(double)</code>, the value will be rounded off to the nearest
+ * integral millisecond using <code>Math.round()</code>.
+ * <p>
+ * The precise number of milliseconds represented by a <code>Duration</code> object can be retrieved
+ * by calling the <code>getMilliseconds</code> method. The value of a <code>Duration</code> object
+ * in a given unit like days or hours can be retrieved by calling one of the following unit methods,
+ * each of which returns a double-precision floating point number:
+ * <p>
+ * <ul>
+ * <li><code>seconds()</code>
+ * <li><code>minutes()</code>
+ * <li><code>hours()</code>
+ * <li><code>days()</code>
+ * </ul>
+ * <p>
+ * Values can be added and subtracted using the <code>add(Duration)</code> and
+ * <code>subtract(Duration)</code> methods, each of which returns a new immutable
+ * <code>Duration</code> object.
+ * <p>
+ * <code>String</code> values can be converted to <code>Duration</code> objects using the static
+ * <code>valueOf</code> factory methods. The <code>String</code> format is the opposite of the one
+ * created by <code>toString()</code>, which converts a <code>Duration</code> object to a readable
+ * form, such as "3.2 hours" or "32.5 minutes". Valid units are: milliseconds, seconds, minutes
+ * hours and days. Correct English plural forms are used in creating <code>String</code> values and
+ * are parsed as well. The <code>Locale</code> is respected and "," will be used instead of "." in
+ * the Eurozone.
+ * <p>
+ * The benchmark method will "benchmark" a <code>Runnable</code> or an {@link ICode} implementing
+ * object, returning a <code>Duration</code> object that represents the amount of time elapsed in
+ * running the code.
+ * <p>
+ * Finally, the <code>sleep</code> method will sleep for the value of a <code>Duration</code>.
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+public class Duration extends AbstractTimeValue
+{
+ private static final long serialVersionUID = 1L;
+
+ /** Constant for maximum duration. */
+ public static final Duration MAXIMUM = milliseconds(Long.MAX_VALUE);
+
+ /** Constant for no duration. */
+ public static final Duration NONE = milliseconds(0);
+
+ /** Constant for one day. */
+ public static final Duration ONE_DAY = days(1);
+
+ /** Constant for one hour. */
+ public static final Duration ONE_HOUR = hours(1);
+
+ /** Constant for on minute. */
+ public static final Duration ONE_MINUTE = minutes(1);
+
+ /** Constant for one second. */
+ public static final Duration ONE_SECOND = seconds(1);
+
+ /** Constant for one week. */
+ public static final Duration ONE_WEEK = days(7);
+
+ /** pattern to match strings */
+ private static final Pattern pattern = Pattern.compile(
+ "([0-9]+([.,][0-9]+)?)\\s+(millisecond|second|minute|hour|day)s?", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * Benchmark the given command.
+ *
+ * @param code
+ * an <code>ICode</code>
+ * @param log
+ * optional logger to use with errors and exceptions
+ * @return the <code>Time</code> value it took to run the code
+ */
+ public static Duration benchmark(final ICode code, final Logger log)
+ {
+ // Get time before running code
+ final Time start = Time.now();
+
+ // Run the code
+ code.run(log);
+
+ // Return the difference
+ return Time.now().subtract(start);
+ }
+
+ /**
+ * Benchmark the given command.
+ *
+ * @param code
+ * a <code>Runnable</code>
+ * @return the <code>Time</code> value it took to run the code
+ */
+ public static Duration benchmark(final Runnable code)
+ {
+ // Get time before running code
+ final Time start = Time.now();
+
+ // Run code
+ code.run();
+
+ // Return the difference
+ return Time.now().subtract(start);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on days.
+ *
+ * @param days
+ * days <code>double</code> value
+ * @return the <code>Duration</code> based on days
+ */
+ public static Duration days(final double days)
+ {
+ return hours(24.0 * days);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on days.
+ *
+ * @param days
+ * days <code>int</code> value
+ * @return the <code>Duration</code> based on days
+ */
+ public static Duration days(final int days)
+ {
+ return hours(24 * days);
+ }
+
+ /**
+ * Calculates the amount of time elapsed since start time.
+ *
+ * @param start
+ * the start <code>Time</code>
+ * @return the elapsed period as a <code>Duration</code>
+ * @throws IllegalStateException
+ * if start <code>Time</code> is in the future
+ */
+ public static Duration elapsed(final Time start)
+ {
+ return start.elapsedSince();
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on hours.
+ *
+ * @param hours
+ * hours <code>double</code> value
+ * @return the <code>Duration</code> based on hours
+ */
+ public static Duration hours(final double hours)
+ {
+ return minutes(60.0 * hours);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on hours.
+ *
+ * @param hours
+ * hours <code>int</code> value
+ * @return the <code>Duration</code> based on hours
+ */
+ public static Duration hours(final int hours)
+ {
+ return minutes(60 * hours);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on milliseconds.
+ *
+ * @param milliseconds
+ * milliseconds <code>double</code> value
+ * @return the <code>Duration</code> based on milliseconds
+ */
+ public static Duration milliseconds(final double milliseconds)
+ {
+ return milliseconds(Math.round(milliseconds));
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on milliseconds.
+ *
+ * @param milliseconds
+ * milliseconds <code>long</code> value
+ * @return the <code>Duration</code> based on milliseconds
+ */
+ public static Duration milliseconds(final long milliseconds)
+ {
+ return new Duration(milliseconds);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on minutes.
+ *
+ * @param minutes
+ * minutes <code>double</code> value
+ * @return the <code>Duration</code> based on minutes
+ */
+ public static Duration minutes(final double minutes)
+ {
+ return seconds(60.0 * minutes);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on minutes.
+ *
+ * @param minutes
+ * minutes <code>int</code> value
+ * @return the <code>Duration</code> based on minutes
+ */
+ public static Duration minutes(final int minutes)
+ {
+ return seconds(60 * minutes);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on seconds.
+ *
+ * @param seconds
+ * seconds <code>double</code> value
+ * @return the <code>Duration</code> based on seconds
+ */
+ public static Duration seconds(final double seconds)
+ {
+ return milliseconds(seconds * 1000.0);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> based on seconds.
+ *
+ * @param seconds
+ * seconds <code>int</code> value
+ * @return the <code>Duration</code> based on seconds
+ */
+ public static Duration seconds(final int seconds)
+ {
+ return milliseconds(seconds * 1000L);
+ }
+
+ /**
+ * Retrieves the given <code>long</code> as a <code>Duration</code>.
+ *
+ * @param time
+ * the duration <code>long</code> value in milliseconds
+ * @return the <code>Duration</code> value
+ */
+ public static Duration valueOf(final long time)
+ {
+ return new Duration(time);
+ }
+
+ /**
+ * Converts the given <code>String</code> to a new <code>Duration</code> object. The string can
+ * take the form of a floating point number followed by a number of milliseconds, seconds,
+ * minutes, hours or days. For example "6 hours" or "3.4 days". Parsing is case-insensitive.
+ *
+ * @param string
+ * a <code>String</code> to parse
+ * @return the <code>Duration</code> value of the given <code>String</code>
+ * @throws StringValueConversionException
+ */
+ public static Duration valueOf(final String string) throws StringValueConversionException
+ {
+ return valueOf(string, Locale.getDefault(Locale.Category.FORMAT));
+ }
+
+ /**
+ * Converts the given <code>String</code> to a new <code>Duration</code> object. The string can
+ * take the form of a floating point number followed by a number of milliseconds, seconds,
+ * minutes, hours or days. For example "6 hours" or "3.4 days". Parsing is case-insensitive.
+ *
+ * @param string
+ * a <code>String</code> to parse
+ * @param locale
+ * the <code>Locale</code> used for parsing
+ * @return the <code>Duration</code> value of the given <code>String</code>
+ * @throws StringValueConversionException
+ */
+ public static Duration valueOf(final String string, final Locale locale)
+ throws StringValueConversionException
+ {
+ final Matcher matcher = pattern.matcher(string);
+
+ if (matcher.matches())
+ {
+ final double value = StringValue.valueOf(matcher.group(1), locale).toDouble();
+ final String units = matcher.group(3);
+
+ if (units.equalsIgnoreCase("millisecond"))
+ {
+ return milliseconds(value);
+ }
+ else if (units.equalsIgnoreCase("second"))
+ {
+ return seconds(value);
+ }
+ else if (units.equalsIgnoreCase("minute"))
+ {
+ return minutes(value);
+ }
+ else if (units.equalsIgnoreCase("hour"))
+ {
+ return hours(value);
+ }
+ else if (units.equalsIgnoreCase("day"))
+ {
+ return days(value);
+ }
+ else
+ {
+ throw new StringValueConversionException("Unrecognized units: " + string);
+ }
+ }
+ else
+ {
+ throw new StringValueConversionException("Unable to parse duration: " + string);
+ }
+ }
+
+ /**
+ * Private constructor forces use of static factory methods.
+ *
+ * @param milliseconds
+ * number of milliseconds in this <code>Duration</code>
+ */
+ protected Duration(final long milliseconds)
+ {
+ super(milliseconds);
+ }
+
+ /**
+ * Adds a given <code>Duration</code> to this <code>Duration</code>.
+ *
+ * @param duration
+ * the <code>Duration</code> to add
+ * @return the sum of the <code>Duration</code>s
+ */
+ public Duration add(final Duration duration)
+ {
+ return valueOf(getMilliseconds() + duration.getMilliseconds());
+ }
+
+ /**
+ * Retrieves the number of days of the current <code>Duration</code>.
+ *
+ * @return number of days of the current <code>Duration</code>
+ */
+ public final double days()
+ {
+ return hours() / 24.0;
+ }
+
+ /**
+ * Retrieves the number of hours of the current <code>Duration</code>.
+ *
+ * @return number of hours of the current <code>Duration</code>
+ */
+ public final double hours()
+ {
+ return minutes() / 60.0;
+ }
+
+ /**
+ * Retrieves the number of minutes of the current <code>Duration</code>.
+ *
+ * @return number of minutes of the current <code>Duration</code>
+ */
+ public final double minutes()
+ {
+ return seconds() / 60.0;
+ }
+
+ /**
+ * Retrieves the number of seconds of the current <code>Duration</code>.
+ *
+ * @return number of seconds of the current <code>Duration</code>
+ */
+ public final double seconds()
+ {
+ return getMilliseconds() / 1000.0;
+ }
+
+ /**
+ * Sleeps for the current <code>Duration</code>.
+ */
+ public final void sleep()
+ {
+ if (getMilliseconds() > 0)
+ {
+ try
+ {
+ Thread.sleep(getMilliseconds());
+ }
+ catch (InterruptedException e)
+ {
+ // Ignored
+ }
+ }
+ }
+
+ /**
+ * Subtracts a given <code>Duration</code> from this <code>Duration</code>.
+ *
+ * @param that
+ * the <code>Duration</code> to subtract
+ * @return this <code>Duration</code> minus that <code>Duration</code>
+ */
+ public Duration subtract(final Duration that)
+ {
+ return valueOf(getMilliseconds() - that.getMilliseconds());
+ }
+
+ /**
+ * Wait for this duration on the given monitor
+ *
+ * @param object
+ * The monitor to wait on
+ */
+ public void wait(final Object object)
+ {
+ try
+ {
+ object.wait(getMilliseconds());
+ }
+ catch (InterruptedException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Retrieves the <code>String</code> representation of this <code>Duration</code> in days,
+ * hours, minutes, seconds or milliseconds, as appropriate. Uses the default <code>Locale</code>
+ * .
+ *
+ * @return a <code>String</code> representation
+ */
+ @Override
+ public String toString()
+ {
+ return toString(Locale.getDefault(Category.FORMAT));
+ }
+
+ /**
+ * Retrieves the <code>String</code> representation of this <code>Duration</code> in days,
+ * hours, minutes, seconds or milliseconds, as appropriate.
+ *
+ * @param locale
+ * a <code>Locale</code>
+ * @return a <code>String</code> representation
+ */
+ public String toString(final Locale locale)
+ {
+ if (getMilliseconds() >= 0)
+ {
+ if (days() >= 1.0)
+ {
+ return unitString(days(), "day", locale);
+ }
+
+ if (hours() >= 1.0)
+ {
+ return unitString(hours(), "hour", locale);
+ }
+
+ if (minutes() >= 1.0)
+ {
+ return unitString(minutes(), "minute", locale);
+ }
+
+ if (seconds() >= 1.0)
+ {
+ return unitString(seconds(), "second", locale);
+ }
+
+ return unitString(getMilliseconds(), "millisecond", locale);
+ }
+ else
+ {
+ return "N/A";
+ }
+ }
+
+ /**
+ * Converts a value to a unit-suffixed value, taking care of English singular/plural suffix.
+ *
+ * @param value
+ * a <code>double</code> value to format
+ * @param units
+ * the units to apply singular or plural suffix to
+ * @param locale
+ * the <code>Locale</code>
+ * @return a <code>String</code> representation
+ */
+ private String unitString(final double value, final String units, final Locale locale)
+ {
+ return StringValue.valueOf(value, locale) + " " + units + ((value > 1.0) ? "s" : "");
+ }
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/ITimeFrameSource.java b/wicket-util/src/main/java/org/apache/wicket/util/time/ITimeFrameSource.java
new file mode 100755
index 0000000..62eb48b
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/ITimeFrameSource.java
@@ -0,0 +1,40 @@
+/*
+ * 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.wicket.util.time;
+
+import java.io.Serializable;
+
+/**
+ * An <code>ITimeFrameSource</code> produces <code>TimeFrame</code> values. The value returned by an
+ * <code>ITimeFrameSource</code> source may vary over time.
+ *
+ * @see TimeFrame
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+public interface ITimeFrameSource extends Serializable
+{
+ /**
+ * Retrieves the current <code>TimeFrame</code> value.
+ *
+ * @return the current <code>TimeFrame</code> value
+ */
+ TimeFrame getTimeFrame();
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/Time.java b/wicket-util/src/main/java/org/apache/wicket/util/time/Time.java
new file mode 100755
index 0000000..2d8597a
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/Time.java
@@ -0,0 +1,614 @@
+/*
+ * 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.wicket.util.time;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * An immutable <code>Time</code> class that represents a specific point in time. The underlying
+ * representation is a <code>long</code> value which holds a number of milliseconds since January 1,
+ * 1970, 0:00 GMT. To represent a duration of time, such as "6 seconds", use the
+ * <code>Duration</code> class. To represent a time period with a start and end time, use the
+ * <code>TimeFrame</code> class. To represent a time of day, use the <code>TimeOfDay</code> class.
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+public final class Time extends AbstractTime
+{
+ private static final long serialVersionUID = 1L;
+
+ /** the beginning of UNIX time: January 1, 1970, 0:00 GMT. */
+ public static final Time START_OF_UNIX_TIME = millis(0);
+
+ /** parser in 'yyyy.MM.dd' format. */
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd",
+ Locale.ENGLISH);
+
+ /** parser in 'yyyy.MM.dd-h.mma' format. */
+ private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy.MM.dd-h.mma",
+ Locale.ENGLISH);
+
+ /** required for rfc1123 date format */
+ private static final String[] DAYS =
+ {"Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+
+ /** required for rfc1123 date format */
+ private static final String[] MONTHS =
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
+
+ /** time zone for greenwich mean time */
+ public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+ /**
+ * Retrieves a <code>Time</code> instance based on the current time.
+ *
+ * @return the current <code>Time</code>
+ */
+ public static Time now()
+ {
+ return millis(System.currentTimeMillis());
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance based on the given milliseconds.
+ *
+ * @param time
+ * the <code>Time</code> value in milliseconds since START_OF_UNIX_TIME
+ * @return a corresponding immutable <code>Time</code> object
+ */
+ public static Time millis(final long time)
+ {
+ return new Time(time);
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance by parsing 'yyyy.MM.dd' format.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use when parsing date <code>String</code>
+ * @param string
+ * the <code>String</code> to parse
+ * @return the time
+ * @throws ParseException
+ */
+ public static Time parseDate(final Calendar calendar, final String string)
+ throws ParseException
+ {
+ synchronized (dateFormat)
+ {
+ synchronized (calendar)
+ {
+ dateFormat.setCalendar(calendar);
+
+ return valueOf(dateFormat.parse(string));
+ }
+ }
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance by parsing 'yyyy.MM.dd' format using a local time
+ * <code>Calendar</code>.
+ *
+ * @param string
+ * the <code>String</code> to parse
+ * @return the time
+ * @throws ParseException
+ */
+ public static Time parseDate(final String string) throws ParseException
+ {
+ return parseDate(localtime, string);
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance by parsing 'yyyy.MM.dd-h.mma' format.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use when parsing the <code>String</code>
+ * @param string
+ * the <code>String</code> to parse
+ * @return an immutable UNIX <code>Time</code> value
+ * @throws ParseException
+ */
+ public static Time valueOf(final Calendar calendar, final String string) throws ParseException
+ {
+ synchronized (dateTimeFormat)
+ {
+ synchronized (calendar)
+ {
+ dateTimeFormat.setCalendar(calendar);
+
+ return valueOf(dateTimeFormat.parse(string));
+ }
+ }
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance based on the given <code>Calendar</code> and
+ * {@link TimeOfDay} objects.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use
+ * @param timeOfDay
+ * the time of day
+ * @return a <code>Time</code> value for the time of day today
+ */
+ public static Time valueOf(final Calendar calendar, final TimeOfDay timeOfDay)
+ {
+ synchronized (calendar)
+ {
+ // Set time to midnight today
+ calendar.setTimeInMillis(System.currentTimeMillis());
+ calendar.set(Calendar.HOUR_OF_DAY, 0); // WICKET-2349
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0); // WICKET-1670
+
+ // Add time of day milliseconds to midnight
+ return millis(calendar.getTimeInMillis() + timeOfDay.getMilliseconds());
+ }
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance based on the given <code>Date</code> object.
+ *
+ * @param date
+ * a <code>java.util.Date</code> object
+ * @return a corresponding immutable <code>Time</code> object
+ */
+ public static Time valueOf(final Date date)
+ {
+ return new Time(date.getTime());
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance by parsing 'yyyy.MM.dd-h.mma' format.
+ *
+ * @param string
+ * the <code>String</code> to parse
+ * @return the <code>Time</code> instance
+ * @throws ParseException
+ */
+ public static Time valueOf(final String string) throws ParseException
+ {
+ return valueOf(localtime, string);
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance by parsing 'pattern' format.
+ *
+ * @param string
+ * input
+ * @param pattern
+ * the pattern to parse
+ * @return a <code>Time</code> instance that resulted from parsing the given <code>String</code>
+ * @throws ParseException
+ */
+ public static Time valueOf(final String string, final String pattern) throws ParseException
+ {
+ final SimpleDateFormat dateTimeFormat = new SimpleDateFormat(pattern, Locale.ENGLISH);
+ dateTimeFormat.setCalendar(localtime);
+ return valueOf(dateTimeFormat.parse(string));
+ }
+
+ /**
+ * Retrieves a <code>Time</code> instance based on the given {@link TimeOfDay} object.
+ *
+ * @param timeOfDay
+ * the time of day in local time
+ * @return a <code>Time</code> value for the time of day today
+ */
+ public static Time valueOf(final TimeOfDay timeOfDay)
+ {
+ return valueOf(localtime, timeOfDay);
+ }
+
+ /**
+ * Private constructor forces use of static factory methods.
+ *
+ * @param time
+ * the <code>Time</code> value in milliseconds since START_OF_UNIX_TIME
+ */
+ private Time(final long time)
+ {
+ super(time);
+ }
+
+ /**
+ * Adds the given <code>Duration</code> to this <code>Time</code> object, moving the time into
+ * the future.
+ *
+ * @param duration
+ * the <code>Duration</code> to add
+ * @return this <code>Time</code> + <code>Duration</code>
+ */
+ public Time add(final Duration duration)
+ {
+ return millis(getMilliseconds() + duration.getMilliseconds());
+ }
+
+ /**
+ * Calculates the amount of time that has elapsed since this <code>Time</code> value.
+ *
+ * @return the amount of time that has elapsed since this <code>Time</code> value
+ * @throws IllegalStateException
+ * thrown if this <code>Time</code> value is in the future
+ */
+ public Duration elapsedSince()
+ {
+ final Time now = now();
+ if (this.greaterThan(now))
+ {
+ throw new IllegalStateException("This time is in the future");
+ }
+ return now.subtract(this);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> from now to this <code>Time</code> value. If this
+ * <code>Time</code> value is in the past, then the <code>Duration</code> returned will be
+ * negative. Otherwise, it will be the number of milliseconds from now to this <code>Time</code>
+ * .
+ *
+ * @return the <code>Duration</code> from now to this <code>Time</code> value
+ */
+ public Duration fromNow()
+ {
+ return subtract(now());
+ }
+
+ /**
+ * Retrieves the value of a field from the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use
+ * @param field
+ * the <code>Calendar</code> field to get
+ * @return the field's value for this point in time on the given <code>Calendar</code>
+ */
+ public int get(final Calendar calendar, final int field)
+ {
+ synchronized (calendar)
+ {
+ calendar.setTimeInMillis(getMilliseconds());
+
+ return calendar.get(field);
+ }
+ }
+
+ /**
+ * Retrieves the value of a field.
+ *
+ * @param field
+ * the <code>Calendar</code> field to get
+ * @return the field's value (in local time)
+ */
+ public int get(final int field)
+ {
+ return get(localtime, field);
+ }
+
+ /**
+ * Retrieves the day of month field of the current <code>Calendar</code>.
+ *
+ * @return the day of month field value
+ */
+ public int getDayOfMonth()
+ {
+ return getDayOfMonth(localtime);
+ }
+
+ /**
+ * Retrieves the day of month field of the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to get the field value from
+ * @return the day of month field value
+ */
+ public int getDayOfMonth(final Calendar calendar)
+ {
+ return get(calendar, Calendar.DAY_OF_MONTH);
+ }
+
+ /**
+ * Retrieves the hour field of the current <code>Calendar</code>.
+ *
+ * @return the hour field value
+ */
+ public int getHour()
+ {
+ return getHour(localtime);
+ }
+
+ /**
+ * Retrieves the hour field of the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to get the field value from
+ * @return the hour field value
+ */
+ public int getHour(final Calendar calendar)
+ {
+ return get(calendar, Calendar.HOUR_OF_DAY);
+ }
+
+ /**
+ * Retrieves the minute field of the current <code>Calendar</code>.
+ *
+ * @return the minute field value
+ */
+ public int getMinute()
+ {
+ return getMinute(localtime);
+ }
+
+ /**
+ * Retrieves the minute field of the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> from which to get the field value
+ * @return the minute field value
+ */
+ public int getMinute(final Calendar calendar)
+ {
+ return get(calendar, Calendar.MINUTE);
+ }
+
+ /**
+ * Retrieves the month field of the current <code>Calendar</code>.
+ *
+ * @return the month field value
+ */
+ public int getMonth()
+ {
+ return getMonth(localtime);
+ }
+
+ /**
+ * Retrieves the month field of the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> from which to get the field value
+ * @return the month field value
+ */
+ public int getMonth(final Calendar calendar)
+ {
+ return get(calendar, Calendar.MONTH);
+ }
+
+ /**
+ * Retrieves the seconds field of the current <code>Calendar</code>.
+ *
+ * @return the seconds field value
+ */
+ public int getSecond()
+ {
+ return getSecond(localtime);
+ }
+
+ /**
+ * Retrieves the seconds field of the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> from which to get the field value
+ * @return the seconds field value
+ */
+ public int getSecond(final Calendar calendar)
+ {
+ return get(calendar, Calendar.SECOND);
+ }
+
+ /**
+ * Retrieves the year field of the current <code>Calendar</code>.
+ *
+ * @return the year field value
+ */
+ public int getYear()
+ {
+ return getYear(localtime);
+ }
+
+ /**
+ * Retrieves the year field of the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> from which to get the field value
+ * @return the year field value
+ */
+ public int getYear(final Calendar calendar)
+ {
+ return get(calendar, Calendar.YEAR);
+ }
+
+ /**
+ * Subtracts the given <code>Duration</code> from this <code>Time</code> object, moving the time
+ * into the past.
+ *
+ * @param duration
+ * the <code>Duration</code> to subtract
+ * @return this duration of time
+ */
+ public Time subtract(final Duration duration)
+ {
+ return millis(getMilliseconds() - duration.getMilliseconds());
+ }
+
+ /**
+ * Subtract time from this and returns the difference as a <code>Duration</code> object.
+ *
+ * @param that
+ * the time to subtract
+ * @return the <code>Duration</code> between this and that time
+ */
+ public Duration subtract(final Time that)
+ {
+ return Duration.milliseconds(getMilliseconds() - that.getMilliseconds());
+ }
+
+ /**
+ * Retrieves a <code>Date</code> object for this <code>Time</code> object. A new
+ * <code>Date</code> object is always returned rather than attempting to cache a date since
+ * <code>Date</code> is mutable.
+ *
+ * @return this immutable <code>Time</code> object as a mutable <code>java.util.Date</code>
+ * object
+ */
+ public Date toDate()
+ {
+ return new Date(getMilliseconds());
+ }
+
+ /**
+ * Converts this <code>Time</code> value to a date <code>String</code> using the date formatter
+ * 'yyyy.MM.dd'.
+ *
+ * @return the date string
+ */
+ public String toDateString()
+ {
+ return toDateString(localtime);
+ }
+
+ /**
+ * Converts this <code>Time</code> value to a date <code>String</code> using the formatter
+ * 'yyyy.MM.dd'.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use in the conversion
+ * @return the date <code>String</code>
+ */
+ public String toDateString(final Calendar calendar)
+ {
+ synchronized (dateFormat)
+ {
+ synchronized (calendar)
+ {
+ dateFormat.setCalendar(calendar);
+
+ return dateFormat.format(new Date(getMilliseconds())).toLowerCase(Locale.ROOT);
+ }
+ }
+ }
+
+ /**
+ * Converts this <code>Time</code> value to a <code>String</code> suitable for use in a file
+ * system name.
+ *
+ * @return this <code>Time</code> value as a formatted <code>String</code>
+ */
+ @Override
+ public String toString()
+ {
+ return toDateString() + "-" + toTimeString();
+ }
+
+ /**
+ * Converts this <code>Time</code> object to a <code>String</code> using the given
+ * <code>Calendar</code> and format.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use in the conversion
+ * @param format
+ * the format to use
+ * @return this <code>Time</code> value as a formatted <code>String</code>
+ */
+ public String toString(final Calendar calendar, final String format)
+ {
+ final SimpleDateFormat dateTimeFormat = new SimpleDateFormat(format, Locale.ENGLISH);
+ dateTimeFormat.setCalendar(calendar == null ? localtime : calendar);
+ return dateTimeFormat.format(new Date(getMilliseconds()));
+ }
+
+ /**
+ * Converts this <code>Time</code> value to a <code>String</code> using the given format.
+ *
+ * @param format
+ * the format to use
+ * @return this <code>Time</code> value as a formatted string
+ */
+ public String toString(final String format)
+ {
+ return toString(null, format);
+ }
+
+ /**
+ * Returns this time stamp in RFC1123 string format. Contrary to
+ * {@link java.text.SimpleDateFormat} this is thread-safe. Taken from the source code of jetty
+ * 7.3.0, credits + thanks to Greg Wilkins!
+ *
+ * @return timestamp string in RFC1123 format
+ */
+ public String toRfc1123TimestampString()
+ {
+ final Calendar cal = GregorianCalendar.getInstance(GMT);
+ final StringBuilder buf = new StringBuilder(32);
+
+ cal.setTimeInMillis(getMilliseconds());
+
+ int day_of_week = cal.get(Calendar.DAY_OF_WEEK);
+ int day_of_month = cal.get(Calendar.DAY_OF_MONTH);
+ int month = cal.get(Calendar.MONTH);
+ int year = cal.get(Calendar.YEAR);
+ int century = year / 100;
+ year = year % 100;
+
+ int hours = cal.get(Calendar.HOUR_OF_DAY);
+ int minutes = cal.get(Calendar.MINUTE);
+ int seconds = cal.get(Calendar.SECOND);
+
+ buf.append(DAYS[day_of_week]);
+ buf.append(',');
+ buf.append(' ');
+ appendTwoDigits(buf, day_of_month);
+
+ buf.append(' ');
+ buf.append(MONTHS[month]);
+ buf.append(' ');
+ appendTwoDigits(buf, century);
+ appendTwoDigits(buf, year);
+
+ buf.append(' ');
+ appendTwoDigits(buf, hours);
+ buf.append(':');
+ appendTwoDigits(buf, minutes);
+ buf.append(':');
+ appendTwoDigits(buf, seconds);
+ buf.append(" GMT");
+
+ return buf.toString();
+ }
+
+ /**
+ * helper method for {@link #toRfc1123TimestampString()}
+ *
+ * @param str
+ * @param number
+ */
+ private static void appendTwoDigits(StringBuilder str, int number)
+ {
+ str.append((char)(number / 10 + '0'));
+ str.append((char)(number % 10 + '0'));
+ }
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/TimeFrame.java b/wicket-util/src/main/java/org/apache/wicket/util/time/TimeFrame.java
new file mode 100755
index 0000000..fc553fd
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/TimeFrame.java
@@ -0,0 +1,260 @@
+/*
+ * 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.wicket.util.time;
+
+import org.apache.wicket.util.lang.Objects;
+
+/**
+ * Immutable class which represents an interval of time with a beginning and an end. The beginning
+ * value is inclusive and the end value is exclusive. In other words, the time frame of 1pm to 2pm
+ * includes 1pm, but not 2pm. 1:59:59 is the last value in the <code>TimeFrame</code>.
+ * <p>
+ * <code>TimeFrame</code>s can be constructed by calling the <code>valueOf</code> static factory
+ * methods <code>valueOf(Time, Time)</code> (yielding a <code>TimeFrame</code> between two absolute
+ * times) and <code>valueOf(Time, Duration)</code> yielding a <code>TimeFrame</code> starting at an
+ * absolute time and having a given length.
+ * <p>
+ * The start and end of a <code>TimeFrame</code> can be retrieved by calling <code>getStart</code>
+ * and <code>getEnd</code>. Its duration can be retrieved by calling <code>getDuration</code>.
+ * <p>
+ * The <code>contains(Time)</code> method can be called to determine if a <code>TimeFrame</code>
+ * contains a given point in time. The <code>overlaps(TimeFrame)</code> method can be called to
+ * determine if two <code>TimeFrames</code> overlap.
+ * <p>
+ * The <code>eachDay(TimeOfDay, TimeOfDay)</code> will return a <code>TimeFrameSource</code> which
+ * generates a <code>TimeFrame</code> using the two times of day. In other words, if the start is
+ * 3pm and the end is 4pm, the <code>TimeFrameSource</code> returned will yield 3-4pm on the day it
+ * is called (each day).
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+public final class TimeFrame implements ITimeFrameSource
+{
+ private static final long serialVersionUID = 1L;
+
+ /** end of this <code>TimeFrame</code> */
+ private final Time end;
+
+ /** beginning of this <code>TimeFrame</code> */
+ private final Time start;
+
+ /**
+ * Creates an <code>ITimeFrameSource</code> source for start and end <code>TimeOfDay</code>s.
+ * For example, called with 3pm and 5pm as parameters, the <code>TimeFrame</code> source
+ * returned would produce <code>TimeFrame</code> objects representing 3pm-5pm on whatever day it
+ * is when the caller calls the <code>TimeFrameSource</code> interface.
+ *
+ * @param startTimeOfDay
+ * the start <code>TimeOfDay</code> for this <code>TimeFrame</code> each day
+ * @param endTimeOfDay
+ * the end <code>TimeOfDay</code> for this <code>TimeFrame</code> each day
+ * @return a <code>TimeFrameSource</code> which will return the specified <code>TimeFrame</code>
+ * each day
+ */
+ public static ITimeFrameSource eachDay(final TimeOfDay startTimeOfDay,
+ final TimeOfDay endTimeOfDay)
+ {
+ check(startTimeOfDay, endTimeOfDay);
+
+ return new ITimeFrameSource()
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public TimeFrame getTimeFrame()
+ {
+ return new TimeFrame(Time.valueOf(startTimeOfDay), Time.valueOf(endTimeOfDay));
+ }
+ };
+ }
+
+ /**
+ * Creates a <code>TimeFrame</code> for a start <code>Time</code> and <code>Duration</code>.
+ *
+ * @param start
+ * the start <code>Time</code>
+ * @param duration
+ * the <code>Duration</code>
+ * @return the <code>TimeFrame</code>
+ * @throws IllegalArgumentException
+ * thrown if start <code>Time</code> value is before end <code>Time</code> value
+ */
+ public static TimeFrame valueOf(final Time start, final Duration duration)
+ {
+ return new TimeFrame(start, start.add(duration));
+ }
+
+ /**
+ * Creates a <code>TimeFrame</code> for given start and end <code>Time</code>s.
+ *
+ * @param start
+ * the start <code>Time</code>
+ * @param end
+ * the end <code>Time</code>
+ * @return the <code>TimeFrame</code>
+ * @throws IllegalArgumentException
+ * thrown if start <code>Time</code> value is before end <code>Time</code> value
+ */
+ public static TimeFrame valueOf(final Time start, final Time end)
+ {
+ return new TimeFrame(start, end);
+ }
+
+ /**
+ * Checks consistency of start and end <code>AbstractTimeValue</code> values, ensuring that the
+ * end value is less than the start value.
+ *
+ * @param start
+ * start <code>AbstractTimeValue</code> value
+ * @param end
+ * end <code>AbstractTimeValue</code> value
+ * @throws IllegalArgumentException
+ * thrown if end is less than start
+ */
+ private static void check(final AbstractTimeValue start, final AbstractTimeValue end)
+ {
+ // Throw illegal argument exception if end is less than start
+ if (end.lessThan(start))
+ {
+ throw new IllegalArgumentException("Start time of time frame " + start +
+ " was after end time " + end);
+ }
+ }
+
+ /**
+ * Private constructor to force use of static factory methods.
+ *
+ * @param start
+ * the start <code>Time</code>
+ * @param end
+ * the end <code>Time</code>
+ * @throws IllegalArgumentException
+ * thrown if start <code>Time</code> value is before end <code>Time</code> value
+ */
+ private TimeFrame(final Time start, final Time end)
+ {
+ check(start, end);
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * Determines if this <code>TimeFrame</code> contains a given point in time.
+ *
+ * @param time
+ * the <code>Time</code> to check
+ * @return <code>true</code> if this <code>TimeFrame</code> contains the given time
+ */
+ public boolean contains(final Time time)
+ {
+ return (start.equals(time) || start.before(time)) && end.after(time);
+ }
+
+ /**
+ * Retrieves the <code>Duration</code> of this <code>TimeFrame</code>.
+ *
+ * @return the <code>Duration</code> of this <code>TimeFrame</code>
+ */
+ public Duration getDuration()
+ {
+ return end.subtract(start);
+ }
+
+ /**
+ * Retrieves the end <code>Time</code> of this <code>TimeFrame</code>.
+ *
+ * @return the end of this <code>TimeFrame</code>
+ */
+ public Time getEnd()
+ {
+ return end;
+ }
+
+ /**
+ * Retrieves the start <code>Time</code> of this <code>TimeFrame</code>.
+ *
+ * @return the start of this <code>TimeFrame</code>
+ */
+ public Time getStart()
+ {
+ return start;
+ }
+
+ /**
+ * Implementation of <code>ITimeFrameSource</code> that simply returns this
+ * <code>TimeFrame</code>.
+ *
+ * @return this <code>TimeFrame</code>
+ */
+ @Override
+ public TimeFrame getTimeFrame()
+ {
+ return this;
+ }
+
+ /**
+ * Determines if two <code>TimeFrame</code>s overlap.
+ *
+ * @param timeframe
+ * the <code>TimeFrame</code> to test
+ * @return <code>true</code> if the given <code>TimeFrame</code> overlaps this one
+ */
+ public boolean overlaps(final TimeFrame timeframe)
+ {
+ return contains(timeframe.start) || contains(timeframe.end) || timeframe.contains(start) ||
+ timeframe.contains(end);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(start, end);
+ }
+
+ @Override
+ public boolean equals(final Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ TimeFrame other = (TimeFrame)obj;
+ return Objects.equal(start, other.start) && Objects.equal(end, other.end);
+ }
+
+ /**
+ * Converts this <code>TimeFrame</code> to a <code>String</code> representation.
+ *
+ * @return a <code>String</code> representation of this object
+ */
+ @Override
+ public String toString()
+ {
+ return "[start=" + start + ", end=" + end + "]";
+ }
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/TimeMap.java b/wicket-util/src/main/java/org/apache/wicket/util/time/TimeMap.java
new file mode 100755
index 0000000..90dd09c
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/TimeMap.java
@@ -0,0 +1,110 @@
+/*
+ * 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.wicket.util.time;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This class maps <code>ITimeFrame</code>s to <code>Object</code>s. Since values are stored using
+ * <code>ITimeFrameSource</code> implementing objects, the value returned by the source may vary
+ * over time. For example, one implementation of <code>ITimeFrameSource</code> might return the
+ * start and end time of lunch on any given day.
+ * <p>
+ * To associate an object with a dynamic <code>TimeFrame</code> (via <code>ITimeFrameSource</code>),
+ * call <code>put(ITimeFrameSource, Object)</code>. You can later retrieve the first object for a
+ * point in time with <code>get(Time)</code>. The <code>get</code> method is provided for
+ * convenience and is equivalent to <code>get(Time.now())</code>.
+ * <p>
+ * This class is not thread-safe.
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+public final class TimeMap implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * <code>Map</code> from <code>ITimeFrameSource</code> implementing objects to
+ * <code>Object</code> values.
+ */
+ private final Map<ITimeFrameSource, Object> sources = new ConcurrentHashMap<>();
+
+ /**
+ * Retrieves an <code>Object</code> for the current <code>Time</code> value.
+ *
+ * @return <code>Object</code> for the current <code>Time</code> value
+ */
+ public Object get()
+ {
+ return get(Time.now());
+ }
+
+ /**
+ * Retrieves an <code>Object</code> for the given <code>Time</code> value.
+ *
+ * @param time
+ * the <code>Time</code> value
+ * @return gets an <code>Object</code> for the given <code>Time</code> value or
+ * <code>null</code> if none exists
+ */
+ public Object get(final Time time)
+ {
+ for (ITimeFrameSource source : sources.keySet())
+ {
+ final TimeFrame current = source.getTimeFrame();
+ if (current.contains(time))
+ {
+ return sources.get(current);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Associates an <code>Object</code> with a dynamic <code>TimeFrame</code>.
+ *
+ * @param source
+ * a source that can produce a <code>TimeFrame</code> with which to compare a
+ * <code>Time</code> value
+ * @param o
+ * the <code>Object</code> to be returned for the given dynamic
+ * <code>TimeFrame</code>
+ */
+ public void put(final ITimeFrameSource source, final Object o)
+ {
+ final TimeFrame timeframe = source.getTimeFrame();
+
+ for (ITimeFrameSource tfs : sources.keySet())
+ {
+ final TimeFrame current = tfs.getTimeFrame();
+
+ if (timeframe.overlaps(current))
+ {
+ throw new IllegalArgumentException("Timeframe " + timeframe +
+ " overlaps timeframe " + current);
+ }
+ }
+
+ sources.put(source, o);
+ }
+}
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/time/TimeOfDay.java b/wicket-util/src/main/java/org/apache/wicket/util/time/TimeOfDay.java
new file mode 100755
index 0000000..183de92
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/time/TimeOfDay.java
@@ -0,0 +1,419 @@
+/*
+ * 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.wicket.util.time;
+
+import java.text.ParseException;
+import java.util.Calendar;
+import org.apache.wicket.util.lang.EnumeratedType;
+
+
+/**
+ * An immutable time of day value represented as milliseconds since the most recent midnight.
+ * <p>
+ * Values can be constructed using various factory methods:
+ * <ul>
+ * <li><code>valueOf(long)</code> where <code>long</code> is milliseconds since midnight
+ * <li><code>valueOf(String)</code> where the <code>String</code> is in 'h.mma' format
+ * <li><code>valueOf(Calendar, String)</code> where the <code>String</code> is in 'h.mma' format
+ * <li><code>valueOf(Duration)</code> where <code>Duration</code> is time since midnight
+ * <li><code>valueOf(Time)</code> where <code>Time</code> is some point in time today
+ * <li><code>valueOf(Calendar, Time)</code> where <code>Time</code> is some point in time today
+ * <li><code>militaryTime(int hour, int minute, int second)</code> for 24-hour time
+ * <li><code>time(int hour, int minute, Meridian)</code> where <code>Meridian</code> is AM or PM
+ * <li><code>time(int hour, int minute, int second, Meridian)</code> where <code>Meridian</code> is
+ * AM or PM
+ * <li><code>now()</code> to construct the current time of day
+ * <li><code>now(Calendar)</code> to construct the current time of day using a given
+ * <code>Calendar</code>
+ * </ul>
+ * <p>
+ * If an attempt is made to construct an illegal time of day value (one that is greater than 24
+ * hours worth of milliseconds), an <code>IllegalArgumentException</code> will be thrown.
+ * <p>
+ * Military hours, minutes and seconds of the time of day can be retrieved by calling the
+ * <code>hour</code>, <code>minute</code>, and <code>second</code> methods.
+ * <p>
+ * The next occurrence of a given <code>TimeOfDay</code> can be retrieved by calling
+ * <code>next()</code> or <code>next(Calendar)</code>.
+ *
+ * @author Jonathan Locke
+ * @since 1.2.6
+ *
+ * @deprecated Since Wicket 9 this class is obsolete and no more used. It will be removed in Wicket 10
+ */
+public final class TimeOfDay extends AbstractTime
+{
+ private static final long serialVersionUID = 1L;
+
+ /** Constant for AM time. */
+ public static final Meridian AM = new Meridian("AM");
+
+ /** Constant for midnight. */
+ public static final TimeOfDay MIDNIGHT = time(12, 0, AM);
+
+ /** Constant for PM time. */
+ public static final Meridian PM = new Meridian("PM");
+
+ /** Constant for noon. */
+ public static final TimeOfDay NOON = time(12, 0, PM);
+
+ /** Typesafe AM/PM enumeration. */
+ public static final class Meridian extends EnumeratedType
+ {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param name
+ * the meridian name (value)
+ */
+ Meridian(final String name)
+ {
+ super(name);
+ }
+ }
+
+ /**
+ * Retrieves a <code>TimeOfDay</code> value on a 24-hour clock.
+ *
+ * @param hour
+ * the hour (0-23)
+ * @param minute
+ * the minute (0-59)
+ * @param second
+ * the second (0-59)
+ * @return the time of day
+ */
+ public static TimeOfDay militaryTime(final int hour, final int minute, final int second)
+ {
+ if ((hour > 23) || (hour < 0))
+ {
+ throw new IllegalArgumentException("Hour " + hour + " is not valid");
+ }
+
+ if ((minute > 59) || (minute < 0))
+ {
+ throw new IllegalArgumentException("Minute " + minute + " is not valid");
+ }
+
+ if ((second > 59) || (second < 0))
+ {
+ throw new IllegalArgumentException("Second " + second + " is not valid");
+ }
+
+ return valueOf(Duration.hours(hour)
+ .add(Duration.minutes(minute))
+ .add(Duration.seconds(second)));
+ }
+
+ /**
+ * Retrieves the <code>TimeOfDay</code> representing 'now'.
+ *
+ * @return the time of day it is now
+ */
+ public static TimeOfDay now()
+ {
+ return valueOf(Time.now());
+ }
+
+ /**
+ * Retrieves the <code>TimeOfDay</code> representing 'now' on the given <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use
+ * @return the time of day it is now on the given <code>Calendar</code>
+ */
+ public static TimeOfDay now(final Calendar calendar)
+ {
+ return valueOf(calendar, Time.now());
+ }
+
+ /**
+ * Retrieves a <code>TimeOfDay</code> on a 12-hour clock.
+ *
+ * @param hour
+ * the hour (1-12)
+ * @param minute
+ * the minute (0-59)
+ * @param second
+ * the second (0-59)
+ * @param meridian
+ * AM or PM
+ * @return the <code>TimeOfDay</code> value
+ */
+ public static TimeOfDay time(final int hour, final int minute, final int second,
+ final Meridian meridian)
+ {
+ if (meridian == PM)
+ {
+ if (hour == 12)
+ {
+ return militaryTime(12, minute, second);
+ }
+ else
+ {
+ return militaryTime(hour + 12, minute, second);
+ }
+ }
+ else
+ {
+ if (hour == 12)
+ {
+ return militaryTime(0, minute, second);
+ }
+ else
+ {
+ return militaryTime(hour, minute, second);
+ }
+ }
+ }
+
+ /**
+ * Retrieves a <code>TimeOfDay</code> on a 12-hour clock.
+ *
+ * @param hour
+ * the hour (1-12)
+ * @param minute
+ * the minute (0-59)
+ * @param meridian
+ * AM of PM
+ * @return the <code>TimeOfDay</code> value
+ */
+ public static TimeOfDay time(final int hour, final int minute, final Meridian meridian)
+ {
+ return time(hour, minute, 0, meridian);
+ }
+
+ /**
+ * Converts a time <code>String</code> and <code>Calendar</code> to a <code>TimeOfDay</code>
+ * instance.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use when parsing time <code>String</code>
+ * @param time
+ * a <code>String</code> in 'h.mma' format
+ * @return the <code>TimeOfDay</code> on the given <code>Calendar</code>
+ * @throws ParseException
+ */
+ public static TimeOfDay valueOf(final Calendar calendar, final String time)
+ throws ParseException
+ {
+ synchronized (timeFormat)
+ {
+ synchronized (calendar)
+ {
+ timeFormat.setCalendar(calendar);
+ return new TimeOfDay(timeFormat.parse(time).getTime());
+ }
+ }
+ }
+
+ /**
+ * Converts a <code>Time</code> instance and <code>Calendar</code> to a <code>TimeOfDay</code>
+ * instance.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use
+ * @param time
+ * a <code>Time</code> instance
+ * @return the <code>TimeOfDay</code> on the given <code>Calendar</code>
+ */
+ public static TimeOfDay valueOf(final Calendar calendar, final Time time)
+ {
+ return militaryTime(time.getHour(calendar), time.getMinute(calendar),
+ time.getSecond(calendar));
+ }
+
+ /**
+ * Converts a <code>Duration</code> instance to a <code>TimeOfDay</code> instance.
+ *
+ * @param duration
+ * the <code>Duration</code> to use
+ * @return the <code>TimeOfDay</code> of the given <code>Duration</code>
+ */
+ public static TimeOfDay valueOf(final Duration duration)
+ {
+ return new TimeOfDay(duration.getMilliseconds());
+ }
+
+ /**
+ * Converts a <code>long</code> value to a <code>TimeOfDay</code> instance.
+ *
+ * @param time
+ * the time in milliseconds today
+ * @return the <code>TimeOfDay</code>
+ */
+ public static TimeOfDay valueOf(final long time)
+ {
+ return new TimeOfDay(time);
+ }
+
+ /**
+ * Converts a <code>String</code> value to a <code>TimeOfDay</code> instance.
+ *
+ * @param time
+ * a <code>String</code> in 'h.mma' format
+ * @return the <code>TimeOfDay</code>
+ * @throws ParseException
+ */
+ public static TimeOfDay valueOf(final String time) throws ParseException
+ {
+ return valueOf(localtime, time);
+ }
+
+ /**
+ * Converts a <code>String</code> value to a <code>TimeOfDay</code> instance.
+ *
+ * @param time
+ * a <code>Time</code> to convert to <code>TimeOfDay</code>
+ * @return the <code>TimeOfDay</code> in the current time zone
+ */
+ public static TimeOfDay valueOf(final Time time)
+ {
+ return valueOf(AbstractTime.localtime, time);
+ }
+
+ /**
+ * Private utility constructor forces use of static factory methods.
+ *
+ * @param time
+ * the time today in milliseconds
+ */
+ private TimeOfDay(final long time)
+ {
+ super(time);
+
+ // A time of day value must be less than 1 day of milliseconds
+ if (Duration.valueOf(time).greaterThan(Duration.ONE_DAY))
+ {
+ throw new IllegalArgumentException("Time " + this + " is not a time of day value");
+ }
+ }
+
+ /**
+ * Retrieves the hour of the day.
+ *
+ * @return the hour (0-23) of this <code>TimeOfDay</code>
+ */
+ public int hour()
+ {
+ return toHours(getMilliseconds());
+ }
+
+ /**
+ * Retrieves the minute.
+ *
+ * @return the minute (0-59) of this <code>TimeOfDay</code>
+ */
+ public int minute()
+ {
+ return toMinutes(getMilliseconds()) % 60;
+ }
+
+ /**
+ * Retrieves the next occurrence of this <code>TimeOfDay</code> in local time.
+ *
+ * @return the next occurrence of this <code>TimeOfDay</code> in local time
+ */
+ public Time next()
+ {
+ return next(AbstractTime.localtime);
+ }
+
+ /**
+ * Retrieves the next occurrence of this <code>TimeOfDay</code> on the given
+ * <code>Calendar</code>.
+ *
+ * @param calendar
+ * the <code>Calendar</code> to use
+ * @return the next occurrence of this <code>TimeOfDay</code> on the given <code>Calendar</code>
+ */
+ public Time next(final Calendar calendar)
+ {
+ // Get this time of day today
+ final Time timeToday = Time.valueOf(calendar, this);
+
+ // If it has already passed
+ if (timeToday.before(Time.now()))
+ {
+ // Return the time tomorrow
+ return Time.valueOf(calendar, this).add(Duration.ONE_DAY);
+ }
+ else
+ {
+ // Time hasn't happened yet today
+ return timeToday;
+ }
+ }
+
+ /**
+ * Retrieves the second.
+ *
+ * @return the second (0-59)
+ */
+ public int second()
+ {
+ return toSeconds(getMilliseconds()) % 60;
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ @Override
+ public String toString()
+ {
+ final int second = second();
+ return "" + hour() + ":" + minute() + (second != 0 ? ":" + second : "");
+ }
+
+ /**
+ * Retrieves milliseconds as hours.
+ *
+ * @param milliseconds
+ * milliseconds to convert
+ * @return converted input
+ */
+ private int toHours(final long milliseconds)
+ {
+ return toMinutes(milliseconds) / 60;
+ }
+
+ /**
+ * Retrieves milliseconds as minutes.
+ *
+ * @param milliseconds
+ * milliseconds to convert
+ * @return converted input
+ */
+ private int toMinutes(final long milliseconds)
+ {
+ return toSeconds(milliseconds) / 60;
+ }
+
+ /**
+ * Retrieves milliseconds as seconds.
+ *
+ * @param milliseconds
+ * milliseconds to convert
+ * @return converted input
+ */
+ private int toSeconds(final long milliseconds)
+ {
+ return (int)(milliseconds / 1000);
+ }
+}