Skip to content

Commit 7cc6195

Browse files
authored
Merge pull request #10205 from grails/GRAILS-10141
Move taglib core date logic to a bean
2 parents a2529c5 + 739cc61 commit 7cc6195

File tree

11 files changed

+344
-52
lines changed

11 files changed

+344
-52
lines changed

grails-databinding/src/main/groovy/org/grails/databinding/converters/DateConversionHelper.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class DateConversionHelper implements ValueConverter {
3232
* This converter attempts to convert a String to a Date, these formats will be tried in
3333
* the order in which they appear in the List.
3434
*/
35-
List<String> formatStrings = ['yyyy-MM-dd HH:mm:ss.S',"yyyy-MM-dd'T'HH:mm:ss'Z'","yyyy-MM-dd HH:mm:ss.S z","yyyy-MM-dd'T'HH:mm:ss.SSSX"]
35+
List<String> formatStrings = []
3636

3737
Object convert(value) {
3838
Date dateValue

grails-databinding/src/test/groovy/grails/databinding/SimpleDataBinderSpec.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ class SimpleDataBinderSpec extends Specification {
205205
void 'Test binding string to date'() {
206206
given:
207207
def binder = new SimpleDataBinder()
208-
binder.registerConverter new DateConversionHelper()
208+
binder.registerConverter new DateConversionHelper(formatStrings: ['yyyy-MM-dd HH:mm:ss.S',"yyyy-MM-dd'T'HH:mm:ss'Z'","yyyy-MM-dd HH:mm:ss.S z","yyyy-MM-dd'T'HH:mm:ss.SSSX"])
209209

210210
def obj = new DateContainer()
211211

grails-databinding/src/test/groovy/org/grails/databinding/converters/DateConversionHelperSpec.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class DateConversionHelperSpec extends Specification {
1212
void 'Test parsing dates'() {
1313
given:
1414
Calendar calendar = getInstance()
15-
DateConversionHelper helper = new DateConversionHelper()
15+
DateConversionHelper helper = new DateConversionHelper(formatStrings: ['yyyy-MM-dd HH:mm:ss.S',"yyyy-MM-dd'T'HH:mm:ss'Z'","yyyy-MM-dd HH:mm:ss.S z","yyyy-MM-dd'T'HH:mm:ss.SSSX"])
1616

1717
when:
1818
Date date = helper.convert '2013-04-15 21:26:31.973'
@@ -85,7 +85,7 @@ class DateConversionHelperSpec extends Specification {
8585

8686
void 'Test invalid format String'() {
8787
given:
88-
def helper = new DateConversionHelper()
88+
def helper = new DateConversionHelper(formatStrings: ['yyyy-MM-dd HH:mm:ss.S'])
8989

9090
when:
9191
helper.convert 'some bogus value'
@@ -96,7 +96,7 @@ class DateConversionHelperSpec extends Specification {
9696

9797
void 'Test formatting an empty String'() {
9898
given:
99-
def helper = new DateConversionHelper()
99+
def helper = new DateConversionHelper(formatStrings: ['yyyy-MM-dd HH:mm:ss.S'])
100100

101101
when:
102102
def date = helper.convert ''

grails-plugin-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingGrailsPlugin.groovy

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class DataBindingGrailsPlugin extends Plugin {
4747
public static final String AUTO_GROW_COLLECTION_LIMIT = 'grails.databinding.autoGrowCollectionLimit'
4848
public static final String DATE_FORMATS = 'grails.databinding.dateFormats'
4949

50+
public static final List<String> DEFAULT_DATE_FORMATS = ['yyyy-MM-dd HH:mm:ss.S',"yyyy-MM-dd'T'HH:mm:ss'Z'","yyyy-MM-dd HH:mm:ss.S z","yyyy-MM-dd'T'HH:mm:ss.SSSX"]
51+
5052
def version = GrailsUtil.getGrailsVersion()
5153

5254
@Override
@@ -56,7 +58,7 @@ class DataBindingGrailsPlugin extends Plugin {
5658
boolean trimStringsSetting = config.getProperty(TRIM_STRINGS, Boolean, true)
5759
boolean convertEmptyStringsToNullSetting = config.getProperty(CONVERT_EMPTY_STRINGS_TO_NULL, Boolean, true)
5860
Integer autoGrowCollectionLimitSetting = config.getProperty(AUTO_GROW_COLLECTION_LIMIT, Integer, 256)
59-
List dateFormats = config.getProperty(DATE_FORMATS, List, [])
61+
List dateFormats = config.getProperty(DATE_FORMATS, List, DEFAULT_DATE_FORMATS)
6062

6163

6264
"${DataBindingUtils.DATA_BINDER_BEAN_NAME}"(GrailsWebDataBinder, grailsApplication) {
@@ -71,9 +73,7 @@ class DataBindingGrailsPlugin extends Plugin {
7173
timeZoneConverter(TimeZoneConverter)
7274

7375
defaultDateConverter(DateConversionHelper) {
74-
if(dateFormats) {
75-
formatStrings = dateFormats
76-
}
76+
formatStrings = dateFormats
7777
}
7878
[Short, Short.TYPE,
7979
Integer, Integer.TYPE,
@@ -101,4 +101,5 @@ class DataBindingGrailsPlugin extends Plugin {
101101

102102
defaultCurrencyConverter CurrencyValueConverter
103103
}}
104+
104105
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright 2004-2005 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.grails.plugins.web
17+
18+
import groovy.transform.CompileStatic
19+
import org.apache.commons.lang.time.FastDateFormat
20+
21+
/**
22+
* The default implementation of {@link GrailsTagDateHelper}
23+
*
24+
* @author James Kleeh
25+
* @since 3.2.1
26+
* @see GrailsTagDateHelper
27+
*/
28+
@CompileStatic
29+
class DefaultGrailsTagDateHelper implements GrailsTagDateHelper {
30+
31+
@Override
32+
Object getTimeZone(Object timeZone) {
33+
if (timeZone != null) {
34+
if (!(timeZone instanceof TimeZone)) {
35+
TimeZone.getTimeZone(timeZone as String)
36+
} else {
37+
timeZone
38+
}
39+
} else {
40+
TimeZone.getDefault()
41+
}
42+
}
43+
44+
@Override
45+
Object getFormatFromPattern(String format, Object timeZone, Locale locale) {
46+
FastDateFormat.getInstance(format, (TimeZone)timeZone, locale)
47+
}
48+
49+
@Override
50+
Object getDateFormat(String style, Object timeZone, Locale locale) {
51+
FastDateFormat.getDateInstance(parseStyle(style), (TimeZone)timeZone, locale)
52+
}
53+
54+
@Override
55+
Object getTimeFormat(String style, Object timeZone, Locale locale) {
56+
FastDateFormat.getTimeInstance(parseStyle(style), (TimeZone)timeZone, locale)
57+
}
58+
59+
@Override
60+
Object getDateTimeFormat(String dateStyle, String timeStyle, Object timeZone, Locale locale) {
61+
FastDateFormat.getDateTimeInstance(parseStyle(dateStyle), parseStyle(timeStyle), (TimeZone)timeZone, locale)
62+
}
63+
64+
@Override
65+
String format(Object formatter, Object date) {
66+
((FastDateFormat)formatter).format(date)
67+
}
68+
69+
private static int parseStyle(String styleStr) {
70+
switch (styleStr) {
71+
case 'FULL': return FastDateFormat.FULL
72+
case 'LONG': return FastDateFormat.LONG
73+
case 'MEDIUM': return FastDateFormat.MEDIUM
74+
default: return FastDateFormat.SHORT
75+
}
76+
}
77+
78+
@Override
79+
Boolean supportsDatePicker(Class clazz) {
80+
clazz == Date
81+
}
82+
83+
@Override
84+
GregorianCalendar buildCalendar(Object date) {
85+
GregorianCalendar c = new GregorianCalendar()
86+
c.setTime((Date)date)
87+
c
88+
}
89+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2004-2005 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.grails.plugins.web
17+
18+
/**
19+
* An interface for defining behavior that Grails tags require surrounding dates
20+
*
21+
* @author James Kleeh
22+
* @since 3.2.1
23+
*/
24+
interface GrailsTagDateHelper {
25+
26+
/**
27+
* Retrieve a time zone object from a parameter
28+
*
29+
* @param timeZone
30+
* @return a time zone to be passed to other methods
31+
*/
32+
Object getTimeZone(Object timeZone)
33+
34+
/**
35+
* Retrieve a date format object to be passed to the {@link #format} method
36+
*
37+
* @param format The string format pattern
38+
* @param timeZone The timeZone retrieved from {@link #getTimeZone}
39+
* @param locale The locale
40+
*/
41+
Object getFormatFromPattern(String format, Object timeZone, Locale locale)
42+
43+
/**
44+
* Retrieve a date format object without time to be passed to the {@link #format} method
45+
*
46+
* @param style The string type of format //FULL,LONG,MEDIUM,SHORT
47+
* @param timeZone The timeZone retrieved from {@link #getTimeZone}
48+
* @param locale The locale
49+
*/
50+
Object getDateFormat(String style, Object timeZone, Locale locale)
51+
52+
/**
53+
* Retrieve a time format object without time to be passed to the {@link #format} method
54+
*
55+
* @param style The string type of format //FULL,LONG,MEDIUM,SHORT
56+
* @param timeZone The timeZone retrieved from {@link #getTimeZone}
57+
* @param locale The locale
58+
*/
59+
Object getTimeFormat(String style, Object timeZone, Locale locale)
60+
61+
/**
62+
* Retrieve a date format object with time to be passed to the {@link #format} method
63+
*
64+
* @param dateStyle The string type of date format //FULL,LONG,MEDIUM,SHORT
65+
* @param timeStyle The string type of time format //FULL,LONG,MEDIUM,SHORT
66+
* @param timeZone The timeZone retrieved from {@link #getTimeZone}
67+
* @param locale The locale
68+
*/
69+
Object getDateTimeFormat(String dateStyle, String timeStyle, Object timeZone, Locale locale)
70+
71+
/**
72+
* Formats a given date
73+
*
74+
* @param formatter The formatter retrieved from any one of these methods: {@link #getFormatFromPattern}, {@link #getDateFormat}, {@link #getTimeFormat}, {@link #getDateTimeFormat}
75+
* @param date The date to be formatted
76+
* @return The string representation of the date
77+
*/
78+
String format(Object formatter, Object date)
79+
80+
/**
81+
* @param clazz The type of date to be used in a date picker
82+
* @return Whether or not the date is supported by the implementation
83+
*/
84+
Boolean supportsDatePicker(Class clazz)
85+
86+
/**
87+
* Creates a GregorianCalendar based off of the date object. This should only get called if {@link #supportsDatePicker} returns true.
88+
*
89+
* @param date The date to convert
90+
* @return A GregorianCalendar instance
91+
*/
92+
GregorianCalendar buildCalendar(Object date)
93+
}

grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@
1515
*/
1616
package org.grails.plugins.web
1717
import grails.config.Config
18-
import grails.core.GrailsClass
1918
import grails.core.GrailsTagLibClass
2019
import grails.gsp.PageRenderer
21-
import grails.io.IOUtils
2220
import grails.plugins.Plugin
2321
import grails.util.BuildSettings
2422
import grails.util.Environment
@@ -33,7 +31,6 @@ import org.grails.gsp.GroovyPageResourceLoader
3331
import org.grails.gsp.GroovyPagesTemplateEngine
3432
import org.grails.gsp.io.CachingGroovyPageStaticResourceLocator
3533
import org.grails.gsp.jsp.TagLibraryResolverImpl
36-
import org.grails.io.support.MainClassFinder
3734
import org.grails.plugins.web.taglib.*
3835
import org.grails.spring.RuntimeSpringConfiguration
3936
import org.grails.taglib.TagLibraryLookup
@@ -50,7 +47,6 @@ import org.grails.web.util.GrailsApplicationAttributes
5047
import org.springframework.beans.factory.config.PropertiesFactoryBean
5148
import org.springframework.boot.context.embedded.ServletRegistrationBean
5249
import org.springframework.core.io.Resource
53-
import org.springframework.core.io.UrlResource
5450
import org.springframework.util.ClassUtils
5551
import org.springframework.web.servlet.view.InternalResourceViewResolver
5652
/**
@@ -288,6 +284,8 @@ class GroovyPagesGrailsPlugin extends Plugin {
288284
initParameters = [showSource:"1"]
289285
}
290286
}
287+
288+
grailsTagDateHelper(DefaultGrailsTagDateHelper)
291289
}}
292290

293291
protected boolean isDevelopmentMode() {

grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ package org.grails.plugins.web.taglib
1818
import grails.artefact.TagLibrary
1919
import grails.gsp.TagLib
2020
import groovy.transform.CompileStatic
21-
import org.springframework.beans.factory.annotation.Autowired
22-
import org.springframework.core.convert.support.DefaultConversionService
23-
import org.springframework.core.convert.support.GenericConversionService
21+
import org.grails.plugins.web.GrailsTagDateHelper
2422

2523
import java.text.DateFormat
2624
import java.text.DateFormatSymbols
@@ -56,6 +54,7 @@ class FormTagLib implements ApplicationContextAware, InitializingBean, TagLibrar
5654
ApplicationContext applicationContext
5755
RequestDataValueProcessor requestDataValueProcessor
5856
ConversionService conversionService
57+
GrailsTagDateHelper grailsTagDateHelper
5958

6059
CodecLookup codecLookup
6160

@@ -578,9 +577,10 @@ class FormTagLib implements ApplicationContextAware, InitializingBean, TagLibrar
578577
else if (xdefault.toString() != 'none') {
579578
if (xdefault instanceof String) {
580579
xdefault = DateFormat.getInstance().parse(xdefault)
580+
581581
}
582-
else if (!(xdefault instanceof Date)) {
583-
throwTagError("Tag [datePicker] requires the default date to be a parseable String or a Date")
582+
else if (!grailsTagDateHelper.supportsDatePicker(xdefault.class)) {
583+
throwTagError("Tag [datePicker] the default date is not a supported class")
584584
}
585585
}
586586
else {
@@ -634,8 +634,7 @@ class FormTagLib implements ApplicationContextAware, InitializingBean, TagLibrar
634634
c = value
635635
}
636636
else if (value != null) {
637-
c = new GregorianCalendar()
638-
c.setTime(value)
637+
c = grailsTagDateHelper.buildCalendar(value)
639638
}
640639

641640
if (c != null) {

0 commit comments

Comments
 (0)