Unverified 提交 67aa05ba authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #676 from imotov/explicit-gregorian-calendar

Use Gregorian calendar regardless of the default locale
...@@ -21,6 +21,8 @@ Change Log ...@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Issue #675: Fix date operations on Locales with non-Gregorian calendars
</li>
<li>Fix removal of LOB when rolling back transaction on a table containing more than one LOB column. <li>Fix removal of LOB when rolling back transaction on a table containing more than one LOB column.
</li> </li>
<li>Issue #654: List ENUM type values in INFORMATION_SCHEMA.COLUMNS <li>Issue #654: List ENUM type values in INFORMATION_SCHEMA.COLUMNS
......
...@@ -1252,7 +1252,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1252,7 +1252,7 @@ public class Function extends Expression implements FunctionCall {
case TRUNCATE: { case TRUNCATE: {
if (v0.getType() == Value.TIMESTAMP) { if (v0.getType() == Value.TIMESTAMP) {
java.sql.Timestamp d = v0.getTimestamp(); java.sql.Timestamp d = v0.getTimestamp();
Calendar c = Calendar.getInstance(); Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTime(d); c.setTime(d);
c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0); c.set(Calendar.MINUTE, 0);
...@@ -1261,7 +1261,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1261,7 +1261,7 @@ public class Function extends Expression implements FunctionCall {
result = ValueTimestamp.fromMillis(c.getTimeInMillis()); result = ValueTimestamp.fromMillis(c.getTimeInMillis());
} else if (v0.getType() == Value.DATE) { } else if (v0.getType() == Value.DATE) {
ValueDate vd = (ValueDate) v0; ValueDate vd = (ValueDate) v0;
Calendar c = Calendar.getInstance(); Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTime(vd.getDate()); c.setTime(vd.getDate());
c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0); c.set(Calendar.MINUTE, 0);
...@@ -1270,7 +1270,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1270,7 +1270,7 @@ public class Function extends Expression implements FunctionCall {
result = ValueTimestamp.fromMillis(c.getTimeInMillis()); result = ValueTimestamp.fromMillis(c.getTimeInMillis());
} else if (v0.getType() == Value.STRING) { } else if (v0.getType() == Value.STRING) {
ValueString vd = (ValueString) v0; ValueString vd = (ValueString) v0;
Calendar c = Calendar.getInstance(); Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTime(ValueTimestamp.parse(vd.getString(), session.getDatabase().getMode()).getDate()); c.setTime(ValueTimestamp.parse(vd.getString(), session.getDatabase().getMode()).getDate());
c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0); c.set(Calendar.MINUTE, 0);
...@@ -1822,7 +1822,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1822,7 +1822,7 @@ public class Function extends Expression implements FunctionCall {
if (count > Integer.MAX_VALUE) { if (count > Integer.MAX_VALUE) {
throw DbException.getInvalidValueException("DATEADD count", count); throw DbException.getInvalidValueException("DATEADD count", count);
} }
Calendar calendar = Calendar.getInstance(); Calendar calendar = DateTimeUtils.createGregorianCalendar();
int nanos = d.getNanos() % 1000000; int nanos = d.getNanos() % 1000000;
calendar.setTime(d); calendar.setTime(d);
calendar.add(field, (int) count); calendar.add(field, (int) count);
...@@ -1846,7 +1846,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1846,7 +1846,7 @@ public class Function extends Expression implements FunctionCall {
*/ */
private static long datediff(String part, Timestamp d1, Timestamp d2) { private static long datediff(String part, Timestamp d1, Timestamp d2) {
int field = getDatePart(part); int field = getDatePart(part);
Calendar calendar = Calendar.getInstance(); Calendar calendar = DateTimeUtils.createGregorianCalendar();
long t1 = d1.getTime(), t2 = d2.getTime(); long t1 = d1.getTime(), t2 = d2.getTime();
// need to convert to UTC, otherwise we get inconsistent results with // need to convert to UTC, otherwise we get inconsistent results with
// certain time zones (those that are 30 minutes off) // certain time zones (those that are 30 minutes off)
...@@ -1896,7 +1896,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1896,7 +1896,7 @@ public class Function extends Expression implements FunctionCall {
default: default:
break; break;
} }
calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar = DateTimeUtils.createGregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(t1); calendar.setTimeInMillis(t1);
int year1 = calendar.get(Calendar.YEAR); int year1 = calendar.get(Calendar.YEAR);
int month1 = calendar.get(Calendar.MONTH); int month1 = calendar.get(Calendar.MONTH);
......
...@@ -3799,7 +3799,7 @@ public class JdbcResultSet extends TraceObject implements ResultSet, JdbcResultS ...@@ -3799,7 +3799,7 @@ public class JdbcResultSet extends TraceObject implements ResultSet, JdbcResultS
} else if (type == java.util.Date.class) { } else if (type == java.util.Date.class) {
return type.cast(new java.util.Date(value.getTimestamp().getTime())); return type.cast(new java.util.Date(value.getTimestamp().getTime()));
} else if (type == Calendar.class) { } else if (type == Calendar.class) {
Calendar calendar = Calendar.getInstance(); Calendar calendar = DateTimeUtils.createGregorianCalendar();
calendar.setTime(value.getTimestamp()); calendar.setTime(value.getTimestamp());
return type.cast(calendar); return type.cast(calendar);
} else if (type == UUID.class) { } else if (type == UUID.class) {
......
...@@ -73,7 +73,7 @@ public class DateTimeUtils { ...@@ -73,7 +73,7 @@ public class DateTimeUtils {
* use a fixed value throughout the duration of the JVM's life, rather than * use a fixed value throughout the duration of the JVM's life, rather than
* have this offset change, possibly midway through a long-running query. * have this offset change, possibly midway through a long-running query.
*/ */
private static int zoneOffsetMillis = Calendar.getInstance() private static int zoneOffsetMillis = DateTimeUtils.createGregorianCalendar()
.get(Calendar.ZONE_OFFSET); .get(Calendar.ZONE_OFFSET);
private DateTimeUtils() { private DateTimeUtils() {
...@@ -86,7 +86,7 @@ public class DateTimeUtils { ...@@ -86,7 +86,7 @@ public class DateTimeUtils {
*/ */
public static void resetCalendar() { public static void resetCalendar() {
CACHED_CALENDAR.remove(); CACHED_CALENDAR.remove();
zoneOffsetMillis = Calendar.getInstance().get(Calendar.ZONE_OFFSET); zoneOffsetMillis = DateTimeUtils.createGregorianCalendar().get(Calendar.ZONE_OFFSET);
} }
/** /**
...@@ -97,7 +97,7 @@ public class DateTimeUtils { ...@@ -97,7 +97,7 @@ public class DateTimeUtils {
private static Calendar getCalendar() { private static Calendar getCalendar() {
Calendar c = CACHED_CALENDAR.get(); Calendar c = CACHED_CALENDAR.get();
if (c == null) { if (c == null) {
c = Calendar.getInstance(); c = DateTimeUtils.createGregorianCalendar();
CACHED_CALENDAR.set(c); CACHED_CALENDAR.set(c);
} }
c.clear(); c.clear();
...@@ -113,13 +113,40 @@ public class DateTimeUtils { ...@@ -113,13 +113,40 @@ public class DateTimeUtils {
private static Calendar getCalendar(TimeZone tz) { private static Calendar getCalendar(TimeZone tz) {
Calendar c = CACHED_CALENDAR_NON_DEFAULT_TIMEZONE.get(); Calendar c = CACHED_CALENDAR_NON_DEFAULT_TIMEZONE.get();
if (c == null || !c.getTimeZone().equals(tz)) { if (c == null || !c.getTimeZone().equals(tz)) {
c = Calendar.getInstance(tz); c = DateTimeUtils.createGregorianCalendar(tz);
CACHED_CALENDAR_NON_DEFAULT_TIMEZONE.set(c); CACHED_CALENDAR_NON_DEFAULT_TIMEZONE.set(c);
} }
c.clear(); c.clear();
return c; return c;
} }
/**
* Creates a Gregorian calendar for the default timezone using the default
* locale. Dates in H2 are represented in a Gregorian calendar. So this
* method should be used instead of Calendar.getInstance() to ensure that
* the Gregorian calendar is used for all date processing instead of a
* default locale calendar that can be non-Gregorian in some locales.
*
* @return a new calendar instance.
*/
public static Calendar createGregorianCalendar() {
return new GregorianCalendar();
}
/**
* Creates a Gregorian calendar for the given timezone using the default
* locale. Dates in H2 are represented in a Gregorian calendar. So this
* method should be used instead of Calendar.getInstance() to ensure that
* the Gregorian calendar is used for all date processing instead of a
* default locale calendar that can be non-Gregorian in some locales.
*
* @param tz timezone for the calendar, is never null
* @return a new calendar instance.
*/
public static Calendar createGregorianCalendar(TimeZone tz) {
return new GregorianCalendar(tz);
}
/** /**
* Convert the date to the specified time zone. * Convert the date to the specified time zone.
* *
...@@ -253,11 +280,9 @@ public class DateTimeUtils { ...@@ -253,11 +280,9 @@ public class DateTimeUtils {
throw DbException.getInvalidValueException("calendar", null); throw DbException.getInvalidValueException("calendar", null);
} }
target = (Calendar) target.clone(); target = (Calendar) target.clone();
Calendar local = Calendar.getInstance(); Calendar local = DateTimeUtils.createGregorianCalendar();
synchronized (local) {
local.setTime(x); local.setTime(x);
convertTime(local, target); convertTime(local, target);
}
return target.getTime().getTime(); return target.getTime().getTime();
} }
...@@ -531,7 +556,7 @@ public class DateTimeUtils { ...@@ -531,7 +556,7 @@ public class DateTimeUtils {
* @return the day of the week, Monday as 1 to Sunday as 7 * @return the day of the week, Monday as 1 to Sunday as 7
*/ */
public static int getIsoDayOfWeek(java.util.Date date) { public static int getIsoDayOfWeek(java.util.Date date) {
Calendar cal = Calendar.getInstance(); Calendar cal = DateTimeUtils.createGregorianCalendar();
cal.setTimeInMillis(date.getTime()); cal.setTimeInMillis(date.getTime());
int val = cal.get(Calendar.DAY_OF_WEEK) - 1; int val = cal.get(Calendar.DAY_OF_WEEK) - 1;
return val == 0 ? 7 : val; return val == 0 ? 7 : val;
...@@ -552,7 +577,7 @@ public class DateTimeUtils { ...@@ -552,7 +577,7 @@ public class DateTimeUtils {
* @return the week of the year * @return the week of the year
*/ */
public static int getIsoWeek(java.util.Date date) { public static int getIsoWeek(java.util.Date date) {
Calendar c = Calendar.getInstance(); Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTimeInMillis(date.getTime()); c.setTimeInMillis(date.getTime());
c.setFirstDayOfWeek(Calendar.MONDAY); c.setFirstDayOfWeek(Calendar.MONDAY);
c.setMinimalDaysInFirstWeek(4); c.setMinimalDaysInFirstWeek(4);
...@@ -567,7 +592,7 @@ public class DateTimeUtils { ...@@ -567,7 +592,7 @@ public class DateTimeUtils {
* @return the year * @return the year
*/ */
public static int getIsoYear(java.util.Date date) { public static int getIsoYear(java.util.Date date) {
Calendar cal = Calendar.getInstance(); Calendar cal = DateTimeUtils.createGregorianCalendar();
cal.setTimeInMillis(date.getTime()); cal.setTimeInMillis(date.getTime());
cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.setMinimalDaysInFirstWeek(4); cal.setMinimalDaysInFirstWeek(4);
...@@ -942,7 +967,7 @@ public class DateTimeUtils { ...@@ -942,7 +967,7 @@ public class DateTimeUtils {
* @return the new timestamp * @return the new timestamp
*/ */
public static Timestamp addMonths(Timestamp refDate, int nrOfMonthsToAdd) { public static Timestamp addMonths(Timestamp refDate, int nrOfMonthsToAdd) {
Calendar calendar = Calendar.getInstance(); Calendar calendar = DateTimeUtils.createGregorianCalendar();
calendar.setTime(refDate); calendar.setTime(refDate);
calendar.add(Calendar.MONTH, nrOfMonthsToAdd); calendar.add(Calendar.MONTH, nrOfMonthsToAdd);
......
...@@ -21,7 +21,7 @@ public class ToDateParser { ...@@ -21,7 +21,7 @@ public class ToDateParser {
private final ConfigParam functionName; private final ConfigParam functionName;
private String inputStr; private String inputStr;
private String formatStr; private String formatStr;
private final Calendar resultCalendar = (Calendar) Calendar.getInstance().clone(); private final Calendar resultCalendar = DateTimeUtils.createGregorianCalendar();
private Integer nanos; private Integer nanos;
/** /**
...@@ -33,7 +33,7 @@ public class ToDateParser { ...@@ -33,7 +33,7 @@ public class ToDateParser {
private ToDateParser(ConfigParam functionName, String input, String format) { private ToDateParser(ConfigParam functionName, String input, String format) {
// reset calendar - default oracle behaviour // reset calendar - default oracle behaviour
resultCalendar.set(Calendar.YEAR, 1970); resultCalendar.set(Calendar.YEAR, 1970);
resultCalendar.set(Calendar.MONTH, Calendar.getInstance().get(Calendar.MONTH)); resultCalendar.set(Calendar.MONTH, DateTimeUtils.createGregorianCalendar().get(Calendar.MONTH));
resultCalendar.clear(Calendar.DAY_OF_YEAR); resultCalendar.clear(Calendar.DAY_OF_YEAR);
resultCalendar.clear(Calendar.DAY_OF_WEEK); resultCalendar.clear(Calendar.DAY_OF_WEEK);
resultCalendar.clear(Calendar.DAY_OF_WEEK_IN_MONTH); resultCalendar.clear(Calendar.DAY_OF_WEEK_IN_MONTH);
......
...@@ -194,7 +194,7 @@ class ToDateTokenizer { ...@@ -194,7 +194,7 @@ class ToDateTokenizer {
result.set(Calendar.YEAR, dateNr); result.set(Calendar.YEAR, dateNr);
break; break;
case RR: case RR:
Calendar calendar = Calendar.getInstance(); Calendar calendar = DateTimeUtils.createGregorianCalendar();
int cc = calendar.get(Calendar.YEAR) / 100; int cc = calendar.get(Calendar.YEAR) / 100;
inputFragmentStr = matchStringOrThrow(PATTERN_TWO_DIGITS, inputFragmentStr = matchStringOrThrow(PATTERN_TWO_DIGITS,
params, formatTokenEnum); params, formatTokenEnum);
......
...@@ -10,7 +10,6 @@ import java.sql.Date; ...@@ -10,7 +10,6 @@ import java.sql.Date;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Calendar;
import java.util.TimeZone; import java.util.TimeZone;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.Mode; import org.h2.engine.Mode;
...@@ -217,7 +216,7 @@ public class ValueTimestamp extends Value { ...@@ -217,7 +216,7 @@ public class ValueTimestamp extends Value {
tz, year, month, day, hour, minute, (int) second, (int) ms); tz, year, month, day, hour, minute, (int) second, (int) ms);
ms = DateTimeUtils.convertToLocal( ms = DateTimeUtils.convertToLocal(
new Date(millis), new Date(millis),
Calendar.getInstance(TimeZone.getTimeZone("UTC"))); DateTimeUtils.createGregorianCalendar(TimeZone.getTimeZone("UTC")));
long md = DateTimeUtils.MILLIS_PER_DAY; long md = DateTimeUtils.MILLIS_PER_DAY;
long absoluteDay = (ms >= 0 ? ms : ms - md + 1) / md; long absoluteDay = (ms >= 0 ? ms : ms - md + 1) / md;
dateValue = DateTimeUtils.dateValueFromAbsoluteDay(absoluteDay); dateValue = DateTimeUtils.dateValueFromAbsoluteDay(absoluteDay);
......
...@@ -1199,7 +1199,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1199,7 +1199,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
"SELECT CURRENT_TIMESTAMP(), " + "SELECT CURRENT_TIMESTAMP(), " +
"TRUNCATE(CURRENT_TIMESTAMP()) FROM dual"); "TRUNCATE(CURRENT_TIMESTAMP()) FROM dual");
rs.next(); rs.next();
Calendar c = Calendar.getInstance(); Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTime(rs.getTimestamp(1)); c.setTime(rs.getTimestamp(1));
c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0); c.set(Calendar.MINUTE, 0);
...@@ -1305,7 +1305,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1305,7 +1305,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
} }
private void testToDate() throws ParseException { private void testToDate() throws ParseException {
final int month = Calendar.getInstance().get(Calendar.MONTH); final int month = DateTimeUtils.createGregorianCalendar().get(Calendar.MONTH);
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");
...@@ -1434,7 +1434,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1434,7 +1434,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
} }
private static void setMonth(Date date, int month) { private static void setMonth(Date date, int month) {
Calendar c = Calendar.getInstance(); Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTime(date); c.setTime(date);
c.set(Calendar.MONTH, month); c.set(Calendar.MONTH, month);
date.setTime(c.getTimeInMillis()); date.setTime(c.getTimeInMillis());
......
...@@ -37,6 +37,7 @@ import java.util.TimeZone; ...@@ -37,6 +37,7 @@ import java.util.TimeZone;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.DateTimeUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.LocalDateTimeUtils; import org.h2.util.LocalDateTimeUtils;
...@@ -1408,7 +1409,7 @@ public class TestResultSet extends TestBase { ...@@ -1408,7 +1409,7 @@ public class TestResultSet extends TestBase {
"D DATE, T TIME, TS TIMESTAMP)"); "D DATE, T TIME, TS TIMESTAMP)");
PreparedStatement prep = conn.prepareStatement( PreparedStatement prep = conn.prepareStatement(
"INSERT INTO TEST VALUES(?, ?, ?, ?)"); "INSERT INTO TEST VALUES(?, ?, ?, ?)");
Calendar regular = Calendar.getInstance(); Calendar regular = DateTimeUtils.createGregorianCalendar();
Calendar other = null; Calendar other = null;
// search a locale that has a _different_ raw offset // search a locale that has a _different_ raw offset
long testTime = java.sql.Date.valueOf("2001-02-03").getTime(); long testTime = java.sql.Date.valueOf("2001-02-03").getTime();
...@@ -1421,7 +1422,7 @@ public class TestResultSet extends TestBase { ...@@ -1421,7 +1422,7 @@ public class TestResultSet extends TestBase {
if (rawOffsetDiff != 0 && rawOffsetDiff != 1000 * 60 * 60 * 24) { if (rawOffsetDiff != 0 && rawOffsetDiff != 1000 * 60 * 60 * 24) {
if (regular.getTimeZone().getOffset(testTime) != if (regular.getTimeZone().getOffset(testTime) !=
zone.getOffset(testTime)) { zone.getOffset(testTime)) {
other = Calendar.getInstance(zone); other = DateTimeUtils.createGregorianCalendar(zone);
break; break;
} }
} }
......
...@@ -42,6 +42,7 @@ import org.h2.test.synth.sql.RandomGen; ...@@ -42,6 +42,7 @@ import org.h2.test.synth.sql.RandomGen;
import org.h2.tools.Backup; import org.h2.tools.Backup;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Restore; import org.h2.tools.Restore;
import org.h2.util.DateTimeUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
...@@ -485,7 +486,7 @@ public class TestCrashAPI extends TestBase implements Runnable { ...@@ -485,7 +486,7 @@ public class TestCrashAPI extends TestBase implements Runnable {
// TODO should use generated savepoints // TODO should use generated savepoints
return null; return null;
} else if (type == Calendar.class) { } else if (type == Calendar.class) {
return Calendar.getInstance(); return DateTimeUtils.createGregorianCalendar();
} else if (type == java.net.URL.class) { } else if (type == java.net.URL.class) {
return null; return null;
} else if (type == java.math.BigDecimal.class) { } else if (type == java.math.BigDecimal.class) {
......
...@@ -352,7 +352,7 @@ public class TestDate extends TestBase { ...@@ -352,7 +352,7 @@ public class TestDate extends TestBase {
} }
private void testValidDate() { private void testValidDate() {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); Calendar c = DateTimeUtils.createGregorianCalendar(TimeZone.getTimeZone("UTC"));
c.setLenient(false); c.setLenient(false);
for (int y = -2000; y < 3000; y++) { for (int y = -2000; y < 3000; y++) {
for (int m = -3; m <= 14; m++) { for (int m = -3; m <= 14; m++) {
...@@ -467,9 +467,9 @@ public class TestDate extends TestBase { ...@@ -467,9 +467,9 @@ public class TestDate extends TestBase {
assertEquals("19999-08-07", d2.getString()); assertEquals("19999-08-07", d2.getString());
assertEquals("13:14:15.16", t2.getString()); assertEquals("13:14:15.16", t2.getString());
ValueTimestamp ts1a = DateTimeUtils.convertTimestamp( ValueTimestamp ts1a = DateTimeUtils.convertTimestamp(
ts1.getTimestamp(), Calendar.getInstance()); ts1.getTimestamp(), DateTimeUtils.createGregorianCalendar());
ValueTimestamp ts2a = DateTimeUtils.convertTimestamp( ValueTimestamp ts2a = DateTimeUtils.convertTimestamp(
ts2.getTimestamp(), Calendar.getInstance()); ts2.getTimestamp(), DateTimeUtils.createGregorianCalendar());
assertEquals("-999-08-07 13:14:15.16", ts1a.getString()); assertEquals("-999-08-07 13:14:15.16", ts1a.getString());
assertEquals("19999-08-07 13:14:15.16", ts2a.getString()); assertEquals("19999-08-07 13:14:15.16", ts2a.getString());
......
...@@ -29,6 +29,7 @@ public class TestLocale extends TestBase { ...@@ -29,6 +29,7 @@ public class TestLocale extends TestBase {
@Override @Override
public void test() throws SQLException { public void test() throws SQLException {
testSpecialLocale(); testSpecialLocale();
testDatesInJapanLocale();
} }
private void testSpecialLocale() throws SQLException { private void testSpecialLocale() throws SQLException {
...@@ -55,4 +56,32 @@ public class TestLocale extends TestBase { ...@@ -55,4 +56,32 @@ public class TestLocale extends TestBase {
conn.close(); conn.close();
} }
private void testDatesInJapanLocale() throws SQLException {
deleteDb(getTestName());
Connection conn = getConnection(getTestName());
Statement stat = conn.createStatement();
Locale old = Locale.getDefault();
try {
// when using Japanese as the default locale, the default calendar is
// the imperial japanese calendar
Locale.setDefault(new Locale("ja", "JP", "JP"));
stat.execute("CREATE TABLE test(d TIMESTAMP, dz TIMESTAMP WITH TIME ZONE) " +
"as select '2017-12-03T00:00:00Z', '2017-12-03T00:00:00Z'");
ResultSet rs = stat.executeQuery("select YEAR(d) y, YEAR(dz) yz from test");
rs.next();
assertEquals(2017, rs.getInt("y"));
assertEquals(2017, rs.getInt("yz"));
stat.execute("drop table test");
rs = stat.executeQuery(
"CALL FORMATDATETIME(TIMESTAMP '2001-02-03 04:05:06', 'yyyy-MM-dd HH:mm:ss', 'en')");
rs.next();
assertEquals("2001-02-03 04:05:06", rs.getString(1));
} finally {
Locale.setDefault(old);
}
conn.close();
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论