You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by so...@apache.org on 2017/10/02 10:13:38 UTC

wicket git commit: DateTimeField is modified to work with LocalDateTime, ZonedDateTimeField is created, code clean-up

Repository: wicket
Updated Branches:
  refs/heads/WICKET-6105-java.time adeae9cea -> aff679fe3


DateTimeField is modified to work with LocalDateTime, ZonedDateTimeField is created, code clean-up


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/aff679fe
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/aff679fe
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/aff679fe

Branch: refs/heads/WICKET-6105-java.time
Commit: aff679fe3c37054202ffc3501ed760abacf53a63
Parents: adeae9c
Author: Maxim Solodovnik <so...@gmail.com>
Authored: Mon Oct 2 17:13:29 2017 +0700
Committer: Maxim Solodovnik <so...@gmail.com>
Committed: Mon Oct 2 17:13:29 2017 +0700

----------------------------------------------------------------------
 wicket-datetime/pom.xml                         |  64 ----
 .../src/main/resources/META-INF/NOTICE          |  11 -
 wicket-datetime/src/test/java/log4j.properties  |  18 --
 .../util/license/ApacheLicenceHeaderTest.java   |  60 ----
 .../util/markup/xhtml/WellFormedXmlTest.java    |  34 ---
 .../form/datetime/AbstractDateTimeField.html    |  23 ++
 .../form/datetime/AbstractDateTimeField.java    | 244 ++++++++++++++++
 .../markup/html/form/datetime/DateLabel.java    | 289 -------------------
 .../html/form/datetime/DateTimeField.html       |  23 --
 .../html/form/datetime/DateTimeField.java       | 199 ++-----------
 .../html/form/datetime/ZonedDateTimeField.java  | 154 ++++++++++
 11 files changed, 443 insertions(+), 676 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-datetime/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-datetime/pom.xml b/wicket-datetime/pom.xml
deleted file mode 100644
index 4a17324..0000000
--- a/wicket-datetime/pom.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>org.apache.wicket</groupId>
-		<artifactId>wicket-parent</artifactId>
-		<version>8.0.0-SNAPSHOT</version>
-		<relativePath>../pom.xml</relativePath>
-	</parent>
-	<artifactId>wicket-datetime</artifactId>
-	<packaging>bundle</packaging>
-	<name>Wicket Date/Time</name>
-	<description>Date/Time components and utilities for Wicket</description>
-	<dependencies>
-		<dependency>
-			<groupId>org.apache.wicket</groupId>
-			<artifactId>wicket-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.wicket</groupId>
-			<artifactId>wicket-extensions</artifactId>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.felix</groupId>
-				<artifactId>maven-bundle-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>bundle-manifest</id>
-						<phase>process-classes</phase>
-						<goals>
-							<goal>manifest</goal>
-						</goals>
-						<configuration>
-							<instructions>
-								<Export-Package>
-									!org.apache.wicket.extensions.yui.yahoo-dom-event,* 
-								</Export-Package>
-							</instructions>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
-		</plugins>
-	</build>
-</project>

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-datetime/src/main/resources/META-INF/NOTICE
----------------------------------------------------------------------
diff --git a/wicket-datetime/src/main/resources/META-INF/NOTICE b/wicket-datetime/src/main/resources/META-INF/NOTICE
deleted file mode 100644
index 48b098e..0000000
--- a/wicket-datetime/src/main/resources/META-INF/NOTICE
+++ /dev/null
@@ -1,11 +0,0 @@
-   Apache Wicket Date Time
-   Copyright 2006-2016 Apache Software Foundation
-
-   This product includes software developed at
-   The Apache Software Foundation (http://www.apache.org/).
-   
-   Contains code of the Yahoo User Interface library (version: 2.8.2r1),
-   released under the BSD License:
-   http://developer.yahoo.net/yui/license.txt
-   Copyright (c) 2010, Yahoo! Inc.
-   
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-datetime/src/test/java/log4j.properties
----------------------------------------------------------------------
diff --git a/wicket-datetime/src/test/java/log4j.properties b/wicket-datetime/src/test/java/log4j.properties
deleted file mode 100644
index e3bc2c7..0000000
--- a/wicket-datetime/src/test/java/log4j.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-log4j.debug=false
-
-log4j.rootLogger=INFO,Stdout
-
-# please keep this setting FATAL to avoid questions from users
-# why there are stacktraces in the test output. You can turn it
-# down if you need to when testing, but don't check it in. (eelco)
-
-# changing back to ERROR. Looks like in some cases the log4j.properties
-# in wicket gets picked which results in not printing the exceptions
-# and that can be a bit dangerous (matej)
-log4j.logger.org.apache.wicket=ERROR
-#log4j.logger.org.apache.wicket.resource=FATAL
-#log4j.logger.org.apache.wicket.Localizer=FATAL
-
-log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-datetime/src/test/java/org/apache/wicket/util/license/ApacheLicenceHeaderTest.java
----------------------------------------------------------------------
diff --git a/wicket-datetime/src/test/java/org/apache/wicket/util/license/ApacheLicenceHeaderTest.java b/wicket-datetime/src/test/java/org/apache/wicket/util/license/ApacheLicenceHeaderTest.java
deleted file mode 100644
index 23887a3..0000000
--- a/wicket-datetime/src/test/java/org/apache/wicket/util/license/ApacheLicenceHeaderTest.java
+++ /dev/null
@@ -1,60 +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.wicket.util.license;
-
-/**
- * Test that the license headers are in place in this project. The tests are run from
- * {@link ApacheLicenseHeaderTestCase}, but you can add project specific tests here if needed.
- * 
- * @author Frank Bille Jensen (frankbille)
- */
-public class ApacheLicenceHeaderTest extends ApacheLicenseHeaderTestCase
-{
-	/**
-	 * Construct.
-	 */
-	public ApacheLicenceHeaderTest()
-	{
-		// addHeaders = true;
-
-		/*
-		 * See NOTICE.txt
-		 */
-		htmlIgnore.add("src/main/java/org/apache/wicket/util/diff");
-
-		/*
-		 * YUI lib. See NOTICE
-		 */
-		cssIgnore.add("src/main/java/org/apache/wicket/extensions/yui/calendar/assets/skins/sam/calendar.css");
-		cssIgnore.add("src/main/java/org/apache/wicket/extensions/yui/calendar/assets/skins/sam/calendar.css");
-
-		/*
-		 * YUI lib. See NOTICE
-		 */
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/yuiloader/yuiloader.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/yuiloader/yuiloader-min.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/yahoo/yahoo.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/yahoo/yahoo-min.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/yahoodomevent/yahoo-dom-event.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/event/event.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/event/event-min.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/dom/dom.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/dom/dom-min.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/calendar/calendar.js");
-		javaScriptIgnore.add("src/main/java/org/apache/wicket/extensions/yui/calendar/calendar-min.js");
-	}
-}

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-datetime/src/test/java/org/apache/wicket/util/markup/xhtml/WellFormedXmlTest.java
----------------------------------------------------------------------
diff --git a/wicket-datetime/src/test/java/org/apache/wicket/util/markup/xhtml/WellFormedXmlTest.java b/wicket-datetime/src/test/java/org/apache/wicket/util/markup/xhtml/WellFormedXmlTest.java
deleted file mode 100644
index a8e7628..0000000
--- a/wicket-datetime/src/test/java/org/apache/wicket/util/markup/xhtml/WellFormedXmlTest.java
+++ /dev/null
@@ -1,34 +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.wicket.util.markup.xhtml;
-
-import org.junit.Test;
-
-/**
- * Checks that the html markup files are well formed xml-s.
- * 
- * @author akiraly
- */
-public class WellFormedXmlTest extends WellFormedXmlTestCase
-{
-	@Test
-	@Override
-	public void markupFiles()
-	{
-		super.markupFiles();
-	}
-}

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.html
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.html b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.html
new file mode 100644
index 0000000..d92f2ce
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.html
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+   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.
+-->
+<wicket:panel xmlns:wicket="http://wicket.apache.org">
+  <span style="white-space: nowrap;">
+    <input type="text" wicket:id="date" size="12" />
+    <span wicket:id="time" />
+  </span>
+</wicket:panel>

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.java
new file mode 100644
index 0000000..5ec27a6
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/AbstractDateTimeField.java
@@ -0,0 +1,244 @@
+/*
+ * 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.extensions.markup.html.form.datetime;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.temporal.Temporal;
+import java.util.Date;
+import java.util.Locale;
+
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.model.IModel;
+
+/**
+ * Works on a {@link java.time.ZonedDateTime} object. Displays a date field and a DatePicker, a field
+ * for hours and a field for minutes, and an AM/PM field. The format (12h/24h) of the hours field
+ * depends on the time format of this {@link AbstractDateTimeField}'s {@link Locale}, as does the visibility
+ * of the AM/PM field (see {@link AbstractDateTimeField#use12HourFormat}).
+ * <p>
+ * <strong>Ajaxifying the DateTimeField</strong>: If you want to update a DateTimeField with an
+ * {@link AjaxFormComponentUpdatingBehavior}, you have to attach it to the contained
+ * {@link DateField} by overriding {@link #newDateTextField(String, IModel)} and calling
+ * {@link #processInput()}:
+ * 
+ * <pre>{@code
+ *  DateTimeField dateTimeField = new DateTimeField(...) {
+ *    protected DateTextField newDateTextField(String id, PropertyModel<Date> dateFieldModel)
+ *    {
+ *      DateTextField dateField = super.newDateTextField(id, dateFieldModel);     
+ *      dateField.add(new AjaxFormComponentUpdatingBehavior("change") {
+ *        protected void onUpdate(AjaxRequestTarget target) {
+ *          processInput(); // let DateTimeField process input too
+ *
+ *          ...
+ *        }
+ *      });
+ *      return recorder;
+ *    }
+ *  }
+ * }</pre>
+ * 
+ * @author eelcohillenius
+ * @see DateField for a variant with just the date field and date picker
+ */
+abstract class AbstractDateTimeField<T extends Temporal> extends FormComponentPanel<T>
+{
+	private static final long serialVersionUID = 1L;
+
+	// Component-IDs
+	protected static final String DATE = "date";
+	protected static final String TIME = "time";
+
+	// The date TextField and it's associated model object
+	// Note that any time information in date will be ignored
+	private DateField dateField;
+	private TimeField timeField;
+
+	/**
+	 * Construct.
+	 * 
+	 * @param id
+	 */
+	public AbstractDateTimeField(final String id)
+	{
+		this(id, null);
+	}
+
+	/**
+	 * Construct.
+	 * 
+	 * @param id
+	 * @param model
+	 */
+	public AbstractDateTimeField(final String id, final IModel<T> model)
+	{
+		super(id, model);
+
+		// Create and add the date TextField
+		add(dateField = newDateField(DATE, new DateModel()));
+		add(timeField = newTimeField(TIME, new TimeModel()));
+	}
+
+	/**
+	 * 
+	 * @return The date TextField
+	 */
+	protected final DateField getDateField()
+	{
+		return dateField;
+	}
+
+	/**
+	 * 
+	 * @return The date TextField
+	 */
+	protected final TimeField getTimeField()
+	{
+		return timeField;
+	}
+
+	@Override
+	public String getInput()
+	{
+		// since we override convertInput, we can let this method return a value
+		// that is just suitable for error reporting
+		return String.format("%s, %s", dateField.getInput(), timeField.getInput());
+	}
+
+	/**
+	 * Sets the converted input, which is an instance of {@link Date}, possibly null. It combines
+	 * the inputs of the nested date, hours, minutes and am/pm fields and constructs a date from it.
+	 * <p>
+	 * Note that overriding this method is a better option than overriding {@link #updateModel()}
+	 * like the first versions of this class did. The reason for that is that this method can be
+	 * used by form validators without having to depend on the actual model being updated, and this
+	 * method is called by the default implementation of {@link #updateModel()} anyway (so we don't
+	 * have to override that anymore).
+	 */
+	@Override
+	public void convertInput()
+	{
+		try
+		{
+			// Get the converted input values
+			LocalDate localDate = dateField.getConvertedInput();
+
+			if (localDate == null)
+			{
+				return;
+			}
+
+			// Use the input to create a date object with proper timezone
+			LocalTime localTime = timeField.getConvertedInput();
+
+			// The date will be in the server's timezone
+			setConvertedInput(performConvert(localDate, localTime));
+		}
+		catch (RuntimeException e)
+		{
+			AbstractDateTimeField.this.error(e.getMessage());
+			invalid();
+		}
+	}
+
+	abstract T performConvert(LocalDate date, LocalTime time);
+
+	abstract void prepareObject();
+
+	/**
+	 * create a new {@link DateField} instance to be added to this panel.
+	 * 
+	 * @param id
+	 *            the component id
+	 * @param dateFieldModel
+	 *            model that should be used by the {@link DateField}
+	 * @return a new date text field instance
+	 */
+	protected DateField newDateField(String id, IModel<LocalDate> dateFieldModel)
+	{
+		return DateField.forShortStyle(id, dateFieldModel);
+	}
+
+	/**
+	 * create a new {@link TimeField} instance to be added to this panel.
+	 * 
+	 * @param id
+	 *            the component id
+	 * @param timeFieldModel
+	 *            model that should be used by the {@link TimeField}
+	 * @return a new time text field instance
+	 */
+	protected TimeField newTimeField(String id, IModel<LocalTime> timeFieldModel)
+	{
+		return TimeField.forShortStyle(id, timeFieldModel);
+	}
+
+	/**
+	 * @see org.apache.wicket.Component#onBeforeRender()
+	 */
+	@Override
+	protected void onBeforeRender()
+	{
+		dateField.setRequired(isRequired());
+		timeField.setRequired(isRequired());
+
+		prepareObject();
+
+		super.onBeforeRender();
+	}
+
+	abstract LocalDate getLocalDate();
+	abstract void setLocalDate(LocalDate date);
+	abstract LocalTime getLocalTime();
+	abstract void setLocalTime(LocalTime time);
+
+	protected class DateModel implements IModel<LocalDate>
+	{
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public LocalDate getObject()
+		{
+			return getLocalDate();
+		}
+
+		@Override
+		public void setObject(LocalDate date)
+		{
+			setLocalDate(date);
+		}
+	}
+
+	protected class TimeModel implements IModel<LocalTime>
+	{
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public LocalTime getObject()
+		{
+			return getLocalTime();
+		}
+
+		@Override
+		public void setObject(LocalTime time)
+		{
+			setLocalTime(time);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateLabel.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateLabel.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateLabel.java
deleted file mode 100644
index 1f8531a..0000000
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateLabel.java
+++ /dev/null
@@ -1,289 +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.wicket.extensions.markup.html.form.datetime;
-
-import java.time.LocalDate;
-import java.time.format.FormatStyle;
-import java.util.Date;
-
-import org.apache.wicket.IGenericComponent;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.MarkupStream;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.util.convert.IConverter;
-import org.apache.wicket.util.lang.Args;
-
-
-/**
- * A label that is mapped to a {@link java.time.LocalDate} object and that uses
- * {@link java.time.format.DateTimeFormatter} to format values.
- * <p>
- * You can provide a date pattern in two of the constructors. When not provided,
- * {@link java.time.format.FormatStyle#SHORT} will be used.
- * </p>
- * <p>
- * A special option is applyTimeZoneDifference which is an option that says whether to correct for
- * the difference between the client's time zone and server's time zone. This is true by default.
- * </p>
- * 
- * @see java.time.LocalDate
- * @see java.time.format.DateTimeFormatter
- */
-public class DateLabel extends Label implements IGenericComponent<LocalDate, DateLabel>
-{
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * Creates a new DateLabel defaulting to using a short date pattern
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param model
-	 *            The model
-	 * @param datePattern
-	 *            The pattern to use. Must be not null. See
-	 *            {@link java.time.format.DateTimeFormatter} for available patterns.
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel forDatePattern(String id, IModel<LocalDate> model, String datePattern)
-	{
-		return new DateLabel(id, model, new PatternZonedDateTimeConverter(datePattern, true));
-	}
-
-	/**
-	 * Creates a new DateLabel defaulting to using a short date pattern
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param datePattern
-	 *            The pattern to use. Must be not null. See
-	 *            {@link java.time.format.DateTimeFormatter} for available patterns.
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel forDatePattern(String id, String datePattern)
-	{
-		return forDatePattern(id, null, datePattern);
-	}
-
-	/**
-	 * Creates a new DateLabel defaulting to using a short date pattern
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param model
-	 *            The model
-	 * @param dateStyle
-	 *            style to use in case no pattern is provided.
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel forDateStyle(String id, IModel<LocalDate> model, FormatStyle dateStyle)
-	{
-		return new DateLabel(id, model, new StyleZonedDateTimeConverter(dateStyle, null, true));
-	}
-
-	/**
-	 * Creates a new DateLabel defaulting to using a short date pattern
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param dateStyle
-	 *            style to use in case no pattern is provided.
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel forDateStyle(String id, FormatStyle dateStyle)
-	{
-		return forDateStyle(id, null, dateStyle);
-	}
-
-	/**
-	 * Creates a new DateLabel defaulting to using a short date pattern
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel forShortStyle(String id)
-	{
-		return forShortStyle(id, null);
-	}
-
-	/**
-	 * Creates a new DateLabel defaulting to using a short date pattern
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param model
-	 *            The model
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel forShortStyle(String id, IModel<LocalDate> model)
-	{
-		return new DateLabel(id, model, new StyleZonedDateTimeConverter(true));
-	}
-
-	/**
-	 * Creates a new DateLabel using the provided converter.
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param converter
-	 *            the date converter
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel withConverter(String id, ZonedDateTimeConverter converter)
-	{
-		return withConverter(id, null, converter);
-	}
-
-	/**
-	 * Creates a new DateLabel using the provided converter.
-	 * 
-	 * @param id
-	 *            The id of the text field
-	 * @param model
-	 *            The model
-	 * @param converter
-	 *            the date converter
-	 * @return new instance
-	 * 
-	 * @see org.apache.wicket.markup.html.form.TextField
-	 */
-	public static DateLabel withConverter(String id, IModel<LocalDate> model, ZonedDateTimeConverter converter)
-	{
-		return new DateLabel(id, model, converter);
-	}
-
-	/** optionally prepend to label. */
-	private String after;
-
-	/** optionally append to label. */
-	private String before;
-
-	/**
-	 * The converter for the Label
-	 */
-	private final ZonedDateTimeConverter converter;
-
-	/**
-	 * Construct with a converter.
-	 * 
-	 * @param id
-	 *            The component id
-	 * @param converter
-	 *            The converter to use
-	 */
-	public DateLabel(String id, ZonedDateTimeConverter converter)
-	{
-		this(id, null, converter);
-	}
-
-	/**
-	 * Construct with a converter.
-	 * 
-	 * @param id
-	 *            The component id
-	 * @param model
-	 *            The model
-	 * @param converter
-	 *            The converter to use
-	 */
-	public DateLabel(String id, IModel<LocalDate> model, ZonedDateTimeConverter converter)
-	{
-		super(id, model);
-		this.converter = Args.notNull(converter, "converter");
-	}
-
-	/**
-	 * @return after append to label or null
-	 */
-	public String getAfter()
-	{
-		return after;
-	}
-
-	/**
-	 * @return before prepend to label or null
-	 */
-	public String getBefore()
-	{
-		return before;
-	}
-
-	/**
-	 * Returns the specialized converter.
-	 */
-	@Override
-	protected IConverter<?> createConverter(Class<?> type)
-	{
-		if (Date.class.isAssignableFrom(type))
-		{
-			return converter;
-		}
-		return null;
-	}
-
-	/**
-	 * @param after
-	 *            append to label
-	 */
-	public void setAfter(String after)
-	{
-		this.after = after;
-	}
-
-	/**
-	 * @param before
-	 *            prepend to label
-	 */
-	public void setBefore(String before)
-	{
-		this.before = before;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag)
-	{
-		String s = getDefaultModelObjectAsString();
-		if (before != null)
-		{
-			s = before + s;
-		}
-		if (after != null)
-		{
-			s = s + after;
-		}
-		replaceComponentTagBody(markupStream, openTag, s);
-	}
-}

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.html
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.html b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.html
deleted file mode 100644
index d92f2ce..0000000
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-   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.
--->
-<wicket:panel xmlns:wicket="http://wicket.apache.org">
-  <span style="white-space: nowrap;">
-    <input type="text" wicket:id="date" size="12" />
-    <span wicket:id="time" />
-  </span>
-</wicket:panel>

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.java
index 0c6531d..8ff825a 100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.java
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/DateTimeField.java
@@ -17,23 +17,16 @@
 package org.apache.wicket.extensions.markup.html.form.datetime;
 
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
 import java.time.temporal.ChronoField;
-import java.util.Date;
 import java.util.Locale;
-import java.util.TimeZone;
 
-import org.apache.wicket.Session;
 import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.core.request.ClientInfo;
-import org.apache.wicket.markup.html.form.FormComponentPanel;
 import org.apache.wicket.model.IModel;
-import org.apache.wicket.protocol.http.request.WebClientInfo;
 
 /**
- * Works on a {@link java.time.ZonedDateTime} object. Displays a date field and a DatePicker, a field
+ * Works on a {@link java.time.LocalDateTimeTime} object. Displays a date field and a DatePicker, a field
  * for hours and a field for minutes, and an AM/PM field. The format (12h/24h) of the hours field
  * depends on the time format of this {@link DateTimeField}'s {@link Locale}, as does the visibility
  * of the AM/PM field (see {@link DateTimeField#use12HourFormat}).
@@ -63,19 +56,11 @@ import org.apache.wicket.protocol.http.request.WebClientInfo;
  * @author eelcohillenius
  * @see DateField for a variant with just the date field and date picker
  */
-public class DateTimeField extends FormComponentPanel<ZonedDateTime>
+public class DateTimeField extends AbstractDateTimeField<LocalDateTime>
 {
 	private static final long serialVersionUID = 1L;
 
-	// Component-IDs
-	protected static final String DATE = "date";
-	protected static final String TIME = "time";
-
-	// The date TextField and it's associated model object
-	// Note that any time information in date will be ignored
-	private DateField dateField;
-	private TimeField timeField;
-	private ZonedDateTime dateTime = ZonedDateTime.now();
+	private LocalDateTime dateTime = LocalDateTime.now();
 
 	/**
 	 * Construct.
@@ -93,186 +78,46 @@ public class DateTimeField extends FormComponentPanel<ZonedDateTime>
 	 * @param id
 	 * @param model
 	 */
-	public DateTimeField(final String id, final IModel<ZonedDateTime> model)
+	public DateTimeField(final String id, final IModel<LocalDateTime> model)
 	{
 		super(id, model);
 
 		// Sets the type that will be used when updating the model for this component.
-		setType(ZonedDateTime.class);
-
-		// Create and add the date TextField
-		add(dateField = newDateField(DATE, new DateModel()));
-		add(timeField = newTimeField(TIME, new TimeModel()));
+		setType(LocalDateTime.class);
 	}
 
-	/**
-	 * 
-	 * @return The date TextField
-	 */
-	protected final DateField getDateField()
-	{
-		return dateField;
-	}
-
-	/**
-	 * 
-	 * @return The date TextField
-	 */
-	protected final TimeField getTimeField()
-	{
-		return timeField;
+	LocalDateTime performConvert(LocalDate date, LocalTime time) {
+		return LocalDateTime.of(date, time);
 	}
 
 	@Override
-	public String getInput()
-	{
-		// since we override convertInput, we can let this method return a value
-		// that is just suitable for error reporting
-		return String.format("%s, %s", dateField.getInput(), timeField.getInput());
-	}
-
-	/**
-	 * Gets the client's time zone.
-	 * 
-	 * @return The client's time zone or null
-	 */
-	protected ZoneId getClientTimeZone()
-	{
-		ClientInfo info = Session.get().getClientInfo();
-		if (info instanceof WebClientInfo)
-		{
-			TimeZone timeZone = ((WebClientInfo) info).getProperties().getTimeZone();
-			return timeZone != null ? timeZone.toZoneId() : null;
-		}
-		return null;
-	}
-
-	/**
-	 * Sets the converted input, which is an instance of {@link Date}, possibly null. It combines
-	 * the inputs of the nested date, hours, minutes and am/pm fields and constructs a date from it.
-	 * <p>
-	 * Note that overriding this method is a better option than overriding {@link #updateModel()}
-	 * like the first versions of this class did. The reason for that is that this method can be
-	 * used by form validators without having to depend on the actual model being updated, and this
-	 * method is called by the default implementation of {@link #updateModel()} anyway (so we don't
-	 * have to override that anymore).
-	 */
-	@Override
-	public void convertInput()
-	{
-		try
-		{
-			// Get the converted input values
-			LocalDate localDate = dateField.getConvertedInput();
-
-			if (localDate == null)
-			{
-				return;
-			}
-
-			// Use the input to create a date object with proper timezone
-			LocalTime localTime = timeField.getConvertedInput();
-			ZonedDateTime date = ZonedDateTime.of(localDate, localTime, getClientTimeZone());
-
-			// The date will be in the server's timezone
-			setConvertedInput(date);
-		}
-		catch (RuntimeException e)
+	void prepareObject() {
+		if (getModelObject() == null)
 		{
-			DateTimeField.this.error(e.getMessage());
-			invalid();
+			dateTime = null;
 		}
 	}
 
-	/**
-	 * create a new {@link DateField} instance to be added to this panel.
-	 * 
-	 * @param id
-	 *            the component id
-	 * @param dateFieldModel
-	 *            model that should be used by the {@link DateField}
-	 * @return a new date text field instance
-	 */
-	protected DateField newDateField(String id, IModel<LocalDate> dateFieldModel)
+	LocalDate getLocalDate()
 	{
-		return DateField.forShortStyle(id, dateFieldModel);
+		return dateTime.toLocalDate();
 	}
 
-	/**
-	 * create a new {@link TimeField} instance to be added to this panel.
-	 * 
-	 * @param id
-	 *            the component id
-	 * @param timeFieldModel
-	 *            model that should be used by the {@link TimeField}
-	 * @return a new time text field instance
-	 */
-	protected TimeField newTimeField(String id, IModel<LocalTime> timeFieldModel)
+	void setLocalDate(LocalDate date)
 	{
-		return TimeField.forShortStyle(id, timeFieldModel);
+		dateTime = dateTime.with(ChronoField.YEAR, date.getYear())
+				.with(ChronoField.MONTH_OF_YEAR, date.getMonthValue())
+				.with(ChronoField.DAY_OF_YEAR, date.getDayOfMonth());
 	}
 
-	/**
-	 * @see org.apache.wicket.Component#onBeforeRender()
-	 */
-	@Override
-	protected void onBeforeRender()
+	LocalTime getLocalTime()
 	{
-		dateField.setRequired(isRequired());
-		timeField.setRequired(isRequired());
-
-		ZonedDateTime modelObject = getModelObject();
-		if (modelObject == null)
-		{
-			dateTime = null;
-		}
-		else
-		{
-			// convert date to the client's time zone if we have that info
-			ZoneId zone = getClientTimeZone();
-			if (zone != null)
-			{
-				modelObject = modelObject.withZoneSameInstant(zone);
-			}
-		}
-
-		super.onBeforeRender();
-	}
-
-	protected class DateModel implements IModel<LocalDate>
-	{
-		private static final long serialVersionUID = 1L;
-
-		@Override
-		public LocalDate getObject()
-		{
-			return dateTime.toLocalDate();
-		}
-
-		@Override
-		public void setObject(LocalDate date)
-		{
-			dateTime = dateTime.with(ChronoField.YEAR, date.getYear());
-			dateTime = dateTime.with(ChronoField.MONTH_OF_YEAR, date.getMonthValue());
-			dateTime = dateTime.with(ChronoField.DAY_OF_YEAR, date.getDayOfMonth());
-		}
+		return dateTime.toLocalTime();
 	}
 
-	protected class TimeModel implements IModel<LocalTime>
+	void setLocalTime(LocalTime time)
 	{
-		private static final long serialVersionUID = 1L;
-
-		@Override
-		public LocalTime getObject()
-		{
-			return dateTime.toLocalTime();
-		}
-
-		@Override
-		public void setObject(LocalTime time)
-		{
-			dateTime = dateTime.with(ChronoField.HOUR_OF_DAY, time.getHour());
-			dateTime = dateTime.with(ChronoField.MINUTE_OF_HOUR, time.getMinute());
-		}
+		dateTime = dateTime.with(ChronoField.HOUR_OF_DAY, time.getHour())
+				.with(ChronoField.MINUTE_OF_HOUR, time.getMinute());
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/aff679fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/ZonedDateTimeField.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/ZonedDateTimeField.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/ZonedDateTimeField.java
new file mode 100644
index 0000000..a6814f8
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/datetime/ZonedDateTimeField.java
@@ -0,0 +1,154 @@
+/*
+ * 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.extensions.markup.html.form.datetime;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoField;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.core.request.ClientInfo;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.protocol.http.request.WebClientInfo;
+
+/**
+ * Works on a {@link java.time.ZonedDateTimeTime} object. Displays a date field and a DatePicker, a field
+ * for hours and a field for minutes, and an AM/PM field. The format (12h/24h) of the hours field
+ * depends on the time format of this {@link ZonedDateTimeField}'s {@link Locale}, as does the visibility
+ * of the AM/PM field (see {@link ZonedDateTimeField#use12HourFormat}).
+ * <p>
+ * <strong>Ajaxifying the DateTimeField</strong>: If you want to update a DateTimeField with an
+ * {@link AjaxFormComponentUpdatingBehavior}, you have to attach it to the contained
+ * {@link DateField} by overriding {@link #newDateTextField(String, IModel)} and calling
+ * {@link #processInput()}:
+ * 
+ * <pre>{@code
+ *  DateTimeField dateTimeField = new DateTimeField(...) {
+ *    protected DateTextField newDateTextField(String id, PropertyModel<Date> dateFieldModel)
+ *    {
+ *      DateTextField dateField = super.newDateTextField(id, dateFieldModel);     
+ *      dateField.add(new AjaxFormComponentUpdatingBehavior("change") {
+ *        protected void onUpdate(AjaxRequestTarget target) {
+ *          processInput(); // let DateTimeField process input too
+ *
+ *          ...
+ *        }
+ *      });
+ *      return recorder;
+ *    }
+ *  }
+ * }</pre>
+ * 
+ * @author eelcohillenius
+ * @see DateField for a variant with just the date field and date picker
+ */
+public class ZonedDateTimeField extends AbstractDateTimeField<ZonedDateTime>
+{
+	private static final long serialVersionUID = 1L;
+
+	private ZonedDateTime dateTime = ZonedDateTime.now();
+
+	/**
+	 * Construct.
+	 * 
+	 * @param id
+	 */
+	public ZonedDateTimeField(final String id)
+	{
+		this(id, null);
+	}
+
+	/**
+	 * Construct.
+	 * 
+	 * @param id
+	 * @param model
+	 */
+	public ZonedDateTimeField(final String id, final IModel<ZonedDateTime> model)
+	{
+		super(id, model);
+
+		// Sets the type that will be used when updating the model for this component.
+		setType(ZonedDateTime.class);
+	}
+
+	/**
+	 * Gets the client's time zone.
+	 * 
+	 * @return The client's time zone or null
+	 */
+	protected ZoneId getClientTimeZone()
+	{
+		ClientInfo info = Session.get().getClientInfo();
+		if (info instanceof WebClientInfo)
+		{
+			TimeZone timeZone = ((WebClientInfo) info).getProperties().getTimeZone();
+			return timeZone != null ? timeZone.toZoneId() : null;
+		}
+		return null;
+	}
+
+	ZonedDateTime performConvert(LocalDate date, LocalTime time) {
+		return ZonedDateTime.of(date, time, getClientTimeZone());
+	}
+
+	@Override
+	void prepareObject() {
+		ZonedDateTime modelObject = getModelObject();
+		if (modelObject == null)
+		{
+			dateTime = null;
+		}
+		else
+		{
+			// convert date to the client's time zone if we have that info
+			ZoneId zone = getClientTimeZone();
+			if (zone != null)
+			{
+				modelObject = modelObject.withZoneSameInstant(zone);
+			}
+		}
+	}
+
+	LocalDate getLocalDate()
+	{
+		return dateTime.toLocalDate();
+	}
+
+	void setLocalDate(LocalDate date)
+	{
+		dateTime = dateTime.with(ChronoField.YEAR, date.getYear())
+				.with(ChronoField.MONTH_OF_YEAR, date.getMonthValue())
+				.with(ChronoField.DAY_OF_YEAR, date.getDayOfMonth());
+	}
+
+	LocalTime getLocalTime()
+	{
+		return dateTime.toLocalTime();
+	}
+
+	void setLocalTime(LocalTime time)
+	{
+		dateTime = dateTime.with(ChronoField.HOUR_OF_DAY, time.getHour())
+				.with(ChronoField.MINUTE_OF_HOUR, time.getMinute());
+	}
+}