/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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.springframework.format.datetime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.validation.DataBinder;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* @author Phillip Webb
* @author Keith Donald
* @author Juergen Hoeller
*/
public class DateFormattingTests {
private final FormattingConversionService conversionService = new FormattingConversionService();
private DataBinder binder;
@Before
public void setUp() {
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
setUp(registrar);
}
private void setUp(DateFormatterRegistrar registrar) {
DefaultConversionService.addDefaultConverters(conversionService);
registrar.registerFormatters(conversionService);
SimpleDateBean bean = new SimpleDateBean();
bean.getChildren().add(new SimpleDateBean());
binder = new DataBinder(bean);
binder.setConversionService(conversionService);
LocaleContextHolder.setLocale(Locale.US);
}
@After
public void tearDown() {
LocaleContextHolder.setLocale(null);
}
@Test
public void testBindLong() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("millis", "1256961600");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("1256961600", binder.getBindingResult().getFieldValue("millis"));
}
@Test
public void testBindLongAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("millisAnnotated", "10/31/09");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("millisAnnotated"));
}
@Test
public void testBindCalendarAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("calendarAnnotated", "10/31/09");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("calendarAnnotated"));
}
@Test
public void testBindDateAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateAnnotated", "10/31/09");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("dateAnnotated"));
}
@Test
public void testBindDateArray() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateAnnotated", new String[]{"10/31/09 12:00 PM"});
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
}
@Test
public void testBindDateAnnotatedWithError() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateAnnotated", "Oct X31, 2009");
binder.bind(propertyValues);
assertEquals(1, binder.getBindingResult().getFieldErrorCount("dateAnnotated"));
assertEquals("Oct X31, 2009", binder.getBindingResult().getFieldValue("dateAnnotated"));
}
@Test
@Ignore
public void testBindDateAnnotatedWithFallbackError() {
// TODO This currently passes because of the Date(String) constructor fallback is used
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateAnnotated", "Oct 031, 2009");
binder.bind(propertyValues);
assertEquals(1, binder.getBindingResult().getFieldErrorCount("dateAnnotated"));
assertEquals("Oct 031, 2009", binder.getBindingResult().getFieldValue("dateAnnotated"));
}
@Test
public void testBindDateAnnotatedPattern() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateAnnotatedPattern", "10/31/09 1:05");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09 1:05", binder.getBindingResult().getFieldValue("dateAnnotatedPattern"));
}
@Test
public void testBindDateTimeOverflow() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("dateAnnotatedPattern", "02/29/09 12:00 PM");
binder.bind(propertyValues);
assertEquals(1, binder.getBindingResult().getErrorCount());
}
@Test
public void testBindISODate() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoDate", "2009-10-31");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("2009-10-31", binder.getBindingResult().getFieldValue("isoDate"));
}
@Test
public void testBindISOTime() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoTime", "12:00:00.000-05:00");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("17:00:00.000Z", binder.getBindingResult().getFieldValue("isoTime"));
}
@Test
public void testBindISODateTime() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("isoDateTime", "2009-10-31T12:00:00.000-08:00");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("2009-10-31T20:00:00.000Z", binder.getBindingResult().getFieldValue("isoDateTime"));
}
@Test
public void testBindNestedDateAnnotated() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("children[0].dateAnnotated", "10/31/09");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("children[0].dateAnnotated"));
}
@Test
public void dateToStringWithoutGlobalFormat() throws Exception {
Date date = new Date();
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
String expected = date.toString();
assertEquals(expected, actual);
}
@Test
public void dateToStringWithGlobalFormat() throws Exception {
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
registrar.setFormatter(new DateFormatter());
setUp(registrar);
Date date = new Date();
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
String expected = new DateFormatter().print(date, Locale.US);
assertEquals(expected, actual);
}
@Test
@SuppressWarnings("deprecation")
public void stringToDateWithoutGlobalFormat() throws Exception {
// SPR-10105
String string = "Sat, 12 Aug 1995 13:30:00 GM";
Date date = this.conversionService.convert(string, Date.class);
assertThat(date, equalTo(new Date(string)));
}
@Test
public void stringToDateWithGlobalFormat() throws Exception {
// SPR-10105
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
DateFormatter dateFormatter = new DateFormatter();
dateFormatter.setIso(ISO.DATE_TIME);
registrar.setFormatter(dateFormatter);
setUp(registrar);
// This is a format that cannot be parsed by new Date(String)
String string = "2009-06-01T14:23:05.003+00:00";
Date date = this.conversionService.convert(string, Date.class);
assertNotNull(date);
}
@SuppressWarnings("unused")
private static class SimpleDateBean {
private Long millis;
private Long millisAnnotated;
@DateTimeFormat(style="S-")
private Calendar calendarAnnotated;
@DateTimeFormat(style="S-")
private Date dateAnnotated;
@DateTimeFormat(pattern="M/d/yy h:mm")
private Date dateAnnotatedPattern;
@DateTimeFormat(iso=ISO.DATE)
private Date isoDate;
@DateTimeFormat(iso=ISO.TIME)
private Date isoTime;
@DateTimeFormat(iso=ISO.DATE_TIME)
private Date isoDateTime;
private final List<SimpleDateBean> children = new ArrayList<>();
public Long getMillis() {
return millis;
}
public void setMillis(Long millis) {
this.millis = millis;
}
@DateTimeFormat(style="S-")
public Long getMillisAnnotated() {
return millisAnnotated;
}
public void setMillisAnnotated(@DateTimeFormat(style="S-") Long millisAnnotated) {
this.millisAnnotated = millisAnnotated;
}
public Calendar getCalendarAnnotated() {
return calendarAnnotated;
}
public void setCalendarAnnotated(Calendar calendarAnnotated) {
this.calendarAnnotated = calendarAnnotated;
}
public Date getDateAnnotated() {
return dateAnnotated;
}
public void setDateAnnotated(Date dateAnnotated) {
this.dateAnnotated = dateAnnotated;
}
public Date getDateAnnotatedPattern() {
return dateAnnotatedPattern;
}
public void setDateAnnotatedPattern(Date dateAnnotatedPattern) {
this.dateAnnotatedPattern = dateAnnotatedPattern;
}
public Date getIsoDate() {
return isoDate;
}
public void setIsoDate(Date isoDate) {
this.isoDate = isoDate;
}
public Date getIsoTime() {
return isoTime;
}
public void setIsoTime(Date isoTime) {
this.isoTime = isoTime;
}
public Date getIsoDateTime() {
return isoDateTime;
}
public void setIsoDateTime(Date isoDateTime) {
this.isoDateTime = isoDateTime;
}
public List<SimpleDateBean> getChildren() {
return children;
}
}
}