提交 0765013e authored 作者: plus33's avatar plus33

Fixed issue #497: TO_DATE reports invalid date format for correct format

to_date failed to parse inline text - E.g. the "T" and "Z" in
to_date('2017-04-21T00:00:00Z', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
上级 443d3627
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
package org.h2.util; package org.h2.util;
import static java.lang.String.format; import static java.lang.String.format;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
...@@ -20,6 +22,7 @@ import java.util.Map; ...@@ -20,6 +22,7 @@ import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.message.DbException; import org.h2.message.DbException;
...@@ -29,6 +32,11 @@ import org.h2.message.DbException; ...@@ -29,6 +32,11 @@ import org.h2.message.DbException;
*/ */
class ToDateTokenizer { class ToDateTokenizer {
/**
* The pattern for a number.
*/
static final Pattern PATTERN_INLINE = Pattern.compile("(\"[^\"]*\")");
/** /**
* The pattern for a number. * The pattern for a number.
*/ */
...@@ -103,6 +111,11 @@ class ToDateTokenizer { ...@@ -103,6 +111,11 @@ class ToDateTokenizer {
*/ */
static final TimeParslet PARSLET_TIME = new TimeParslet(); static final TimeParslet PARSLET_TIME = new TimeParslet();
/**
* The inline parslet. E.g. 'YYYY-MM-DD"T"HH24:MI:SS"Z"' where "T" and "Z" are inlined
*/
static final InlineParslet PARSLET_INLINE = new InlineParslet();
/** /**
* The number of milliseconds in a day. * The number of milliseconds in a day.
*/ */
...@@ -472,6 +485,27 @@ class ToDateTokenizer { ...@@ -472,6 +485,27 @@ class ToDateTokenizer {
} }
} }
/**
* Parslet responsible for parsing year parameter
*/
static class InlineParslet implements ToDateParslet {
@Override
public void parse(ToDateParser params, FormatTokenEnum formatTokenEnum, String formatTokenStr) {
String inputFragmentStr = null;
switch (formatTokenEnum) {
case INLINE:
inputFragmentStr = formatTokenStr.replace("\"", "");
break;
default:
throw new IllegalArgumentException(format(
"%s: Internal Error. Unhandled case: %s", this.getClass()
.getSimpleName(), formatTokenEnum));
}
params.remove(inputFragmentStr, formatTokenStr);
}
}
/** /**
* Match the pattern, or if not possible throw an exception. * Match the pattern, or if not possible throw an exception.
* *
...@@ -610,10 +644,11 @@ class ToDateTokenizer { ...@@ -610,10 +644,11 @@ class ToDateTokenizer {
D(PARSLET_DAY), D(PARSLET_DAY),
// NOT supported yet - // NOT supported yet -
// Julian day; the number of days since Jan 1, 4712 BC. // Julian day; the number of days since Jan 1, 4712 BC.
J(PARSLET_DAY); J(PARSLET_DAY),
// Inline text e.g. to_date('2017-04-21T00:00:00Z', 'YYYY-MM-DD"T"HH24:MI:SS"Z"') where "T" and "Z" are inlined
INLINE(PARSLET_INLINE, PATTERN_INLINE);
private static final List<FormatTokenEnum> EMPTY_LIST = private static final List<FormatTokenEnum> EMPTY_LIST = Collections.emptyList();
new ArrayList<>(0);
private static final Map<Character, List<FormatTokenEnum>> CACHE = private static final Map<Character, List<FormatTokenEnum>> CACHE =
new HashMap<>(FormatTokenEnum.values().length); new HashMap<>(FormatTokenEnum.values().length);
...@@ -656,7 +691,14 @@ class ToDateTokenizer { ...@@ -656,7 +691,14 @@ class ToDateTokenizer {
} }
if (formatStr != null && formatStr.length() > 0) { if (formatStr != null && formatStr.length() > 0) {
Character key = Character.toUpperCase(formatStr.charAt(0)); Character key = Character.toUpperCase(formatStr.charAt(0));
result = CACHE.get(key); switch (key) {
case '"':
result = new ArrayList<FormatTokenEnum>();
result.add(INLINE);
break;
default:
result = CACHE.get(key);
}
} }
if (result == null) { if (result == null) {
result = EMPTY_LIST; result = EMPTY_LIST;
......
...@@ -1309,6 +1309,8 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1309,6 +1309,8 @@ public class TestFunctions extends TestBase implements AggregateFunction {
Date date = null; Date date = null;
date = new SimpleDateFormat("yyyy-MM-dd").parse("1979-11-12"); date = new SimpleDateFormat("yyyy-MM-dd").parse("1979-11-12");
assertEquals(date, ToDateParser.toDate("1979-11-12T00:00:00Z", "YYYY-MM-DD\"T\"HH24:MI:SS\"Z\""));
assertEquals(date, ToDateParser.toDate("1979*foo*1112", "YYYY\"*foo*\"MM\"\"DD"));
assertEquals(date, ToDateParser.toDate("1979-11-12", "YYYY-MM-DD")); assertEquals(date, ToDateParser.toDate("1979-11-12", "YYYY-MM-DD"));
assertEquals(date, ToDateParser.toDate("1979/11/12", "YYYY/MM/DD")); assertEquals(date, ToDateParser.toDate("1979/11/12", "YYYY/MM/DD"));
assertEquals(date, ToDateParser.toDate("1979,11,12", "YYYY,MM,DD")); assertEquals(date, ToDateParser.toDate("1979,11,12", "YYYY,MM,DD"));
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论