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

Merge pull request #805 from katzyn/datetime

Improve support of TIMESTAMP WITH TIME ZONE
...@@ -837,28 +837,22 @@ public class Function extends Expression implements FunctionCall { ...@@ -837,28 +837,22 @@ public class Function extends Expression implements FunctionCall {
break; break;
} }
case DAY_OF_MONTH: case DAY_OF_MONTH:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.DAY_OF_MONTH));
Calendar.DAY_OF_MONTH));
break; break;
case DAY_OF_WEEK: case DAY_OF_WEEK:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.DAY_OF_WEEK));
Calendar.DAY_OF_WEEK));
break; break;
case DAY_OF_YEAR: case DAY_OF_YEAR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.DAY_OF_YEAR));
Calendar.DAY_OF_YEAR));
break; break;
case HOUR: case HOUR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getTimestamp(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.HOUR_OF_DAY));
Calendar.HOUR_OF_DAY));
break; break;
case MINUTE: case MINUTE:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getTimestamp(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.MINUTE));
Calendar.MINUTE));
break; break;
case MONTH: case MONTH:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.MONTH));
Calendar.MONTH));
break; break;
case MONTH_NAME: { case MONTH_NAME: {
SimpleDateFormat monthName = new SimpleDateFormat("MMMM", SimpleDateFormat monthName = new SimpleDateFormat("MMMM",
...@@ -868,29 +862,25 @@ public class Function extends Expression implements FunctionCall { ...@@ -868,29 +862,25 @@ public class Function extends Expression implements FunctionCall {
break; break;
} }
case QUARTER: case QUARTER:
result = ValueInt.get((DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get((DateTimeUtils.getDatePart(v0, Calendar.MONTH) - 1) / 3 + 1);
Calendar.MONTH) - 1) / 3 + 1);
break; break;
case SECOND: case SECOND:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getTimestamp(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.SECOND));
Calendar.SECOND));
break; break;
case WEEK: case WEEK:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.WEEK_OF_YEAR));
Calendar.WEEK_OF_YEAR));
break; break;
case YEAR: case YEAR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(), result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.YEAR));
Calendar.YEAR));
break; break;
case ISO_YEAR: case ISO_YEAR:
result = ValueInt.get(DateTimeUtils.getIsoYear(v0.getDate())); result = ValueInt.get(DateTimeUtils.getIsoYear(v0));
break; break;
case ISO_WEEK: case ISO_WEEK:
result = ValueInt.get(DateTimeUtils.getIsoWeek(v0.getDate())); result = ValueInt.get(DateTimeUtils.getIsoWeek(v0));
break; break;
case ISO_DAY_OF_WEEK: case ISO_DAY_OF_WEEK:
result = ValueInt.get(DateTimeUtils.getIsoDayOfWeek(v0.getDate())); result = ValueInt.get(DateTimeUtils.getIsoDayOfWeek(v0));
break; break;
case CURDATE: case CURDATE:
case CURRENT_DATE: { case CURRENT_DATE: {
...@@ -1523,8 +1513,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1523,8 +1513,7 @@ public class Function extends Expression implements FunctionCall {
break; break;
case EXTRACT: { case EXTRACT: {
int field = getDatePart(v0.getString()); int field = getDatePart(v0.getString());
result = ValueInt.get(DateTimeUtils.getDatePart( result = ValueInt.get(DateTimeUtils.getDatePart(v1, field));
v1.getTimestamp(), field));
break; break;
} }
case FORMATDATETIME: { case FORMATDATETIME: {
......
...@@ -21,6 +21,7 @@ import org.h2.value.ValueDate; ...@@ -21,6 +21,7 @@ import org.h2.value.ValueDate;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
import org.h2.value.ValueTime; import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp; import org.h2.value.ValueTimestamp;
import org.h2.value.ValueTimestampTimeZone;
/** /**
* This utility class contains time conversion functions. * This utility class contains time conversion functions.
...@@ -317,6 +318,30 @@ public class DateTimeUtils { ...@@ -317,6 +318,30 @@ public class DateTimeUtils {
return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos); return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
} }
private static Calendar valueToCalendar(Value value) {
Calendar cal;
if (value instanceof ValueTimestamp) {
cal = createGregorianCalendar();
cal.setTime(value.getTimestamp());
} else if (value instanceof ValueDate) {
cal = createGregorianCalendar();
cal.setTime(value.getDate());
} else if (value instanceof ValueTime) {
cal = createGregorianCalendar();
cal.setTime(value.getTime());
} else if (value instanceof ValueTimestampTimeZone) {
ValueTimestampTimeZone v = (ValueTimestampTimeZone) value;
cal = createGregorianCalendar(v.getTimeZone());
cal.setTimeInMillis(DateTimeUtils.convertDateValueToMillis(DateTimeUtils.UTC, v.getDateValue())
+ v.getTimeNanos() / 1000000L
- v.getTimeZoneOffsetMins() * 60000);
} else {
cal = createGregorianCalendar();
cal.setTime(value.getTimestamp());
}
return cal;
}
/** /**
* Parse a date string. The format is: [+|-]year-month-day * Parse a date string. The format is: [+|-]year-month-day
* *
...@@ -494,13 +519,12 @@ public class DateTimeUtils { ...@@ -494,13 +519,12 @@ public class DateTimeUtils {
* Get the specified field of a date, however with years normalized to * Get the specified field of a date, however with years normalized to
* positive or negative, and month starting with 1. * positive or negative, and month starting with 1.
* *
* @param d the date * @param date the date value
* @param field the field type * @param field the field type
* @return the value * @return the value
*/ */
public static int getDatePart(java.util.Date d, int field) { public static int getDatePart(Value date, int field) {
Calendar c = getCalendar(); Calendar c = valueToCalendar(date);
c.setTime(d);
if (field == Calendar.YEAR) { if (field == Calendar.YEAR) {
return getYear(c); return getYear(c);
} }
...@@ -552,13 +576,11 @@ public class DateTimeUtils { ...@@ -552,13 +576,11 @@ public class DateTimeUtils {
* starts at Monday. See also http://en.wikipedia.org/wiki/ISO_8601 * starts at Monday. See also http://en.wikipedia.org/wiki/ISO_8601
* *
* @author Robert Rathsack * @author Robert Rathsack
* @param date the date object which day of week should be calculated * @param value the date object which day of week should be calculated
* @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(Value value) {
Calendar cal = DateTimeUtils.createGregorianCalendar(); int val = valueToCalendar(value).get(Calendar.DAY_OF_WEEK) - 1;
cal.setTimeInMillis(date.getTime());
int val = cal.get(Calendar.DAY_OF_WEEK) - 1;
return val == 0 ? 7 : val; return val == 0 ? 7 : val;
} }
...@@ -573,12 +595,11 @@ public class DateTimeUtils { ...@@ -573,12 +595,11 @@ public class DateTimeUtils {
* the December 28th always belongs to the last week. * the December 28th always belongs to the last week.
* *
* @author Robert Rathsack * @author Robert Rathsack
* @param date the date object which week of year should be calculated * @param value the date object which week of year should be calculated
* @return the week of the year * @return the week of the year
*/ */
public static int getIsoWeek(java.util.Date date) { public static int getIsoWeek(Value value) {
Calendar c = DateTimeUtils.createGregorianCalendar(); Calendar c = valueToCalendar(value);
c.setTimeInMillis(date.getTime());
c.setFirstDayOfWeek(Calendar.MONDAY); c.setFirstDayOfWeek(Calendar.MONDAY);
c.setMinimalDaysInFirstWeek(4); c.setMinimalDaysInFirstWeek(4);
return c.get(Calendar.WEEK_OF_YEAR); return c.get(Calendar.WEEK_OF_YEAR);
...@@ -588,12 +609,11 @@ public class DateTimeUtils { ...@@ -588,12 +609,11 @@ public class DateTimeUtils {
* Returns the year according to the ISO week definition. * Returns the year according to the ISO week definition.
* *
* @author Robert Rathsack * @author Robert Rathsack
* @param date the date object which year should be calculated * @param value the date object which year should be calculated
* @return the year * @return the year
*/ */
public static int getIsoYear(java.util.Date date) { public static int getIsoYear(Value value) {
Calendar cal = DateTimeUtils.createGregorianCalendar(); Calendar cal = valueToCalendar(value);
cal.setTimeInMillis(date.getTime());
cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.setMinimalDaysInFirstWeek(4); cal.setMinimalDaysInFirstWeek(4);
int year = getYear(cal); int year = getYear(cal);
......
...@@ -9,6 +9,7 @@ import java.math.BigDecimal; ...@@ -9,6 +9,7 @@ import java.math.BigDecimal;
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.SimpleTimeZone;
import java.util.TimeZone; import java.util.TimeZone;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.TimestampWithTimeZone; import org.h2.api.TimestampWithTimeZone;
...@@ -50,7 +51,8 @@ public class ValueTimestampTimeZone extends Value { ...@@ -50,7 +51,8 @@ public class ValueTimestampTimeZone extends Value {
*/ */
private final long timeNanos; private final long timeNanos;
/** /**
* Time zone offset from UTC in minutes, range of -12hours to +12hours * Time zone offset from UTC in minutes, range of -18 hours to +18 hours. This
* range is compatible with OffsetDateTime from JSR-310.
*/ */
private final short timeZoneOffsetMins; private final short timeZoneOffsetMins;
...@@ -60,8 +62,13 @@ public class ValueTimestampTimeZone extends Value { ...@@ -60,8 +62,13 @@ public class ValueTimestampTimeZone extends Value {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"timeNanos out of range " + timeNanos); "timeNanos out of range " + timeNanos);
} }
if (timeZoneOffsetMins < (-12 * 60) /*
|| timeZoneOffsetMins >= (12 * 60)) { * Some current and historic time zones have offsets larger than 12 hours.
* JSR-310 determines 18 hours as maximum possible offset in both directions, so
* we use this limit too for compatibility.
*/
if (timeZoneOffsetMins < (-18 * 60)
|| timeZoneOffsetMins > (18 * 60)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"timeZoneOffsetMins out of range " + timeZoneOffsetMins); "timeZoneOffsetMins out of range " + timeZoneOffsetMins);
} }
...@@ -201,6 +208,19 @@ public class ValueTimestampTimeZone extends Value { ...@@ -201,6 +208,19 @@ public class ValueTimestampTimeZone extends Value {
return timeZoneOffsetMins; return timeZoneOffsetMins;
} }
/**
* Returns compatible offset-based time zone with no DST schedule.
*
* @return compatible offset-based time zone
*/
public TimeZone getTimeZone() {
int offset = timeZoneOffsetMins;
if (offset == 0) {
return DateTimeUtils.UTC;
}
return new SimpleTimeZone(offset * 60000, Integer.toString(offset));
}
@Override @Override
public Timestamp getTimestamp() { public Timestamp getTimestamp() {
throw new UnsupportedOperationException("unimplemented"); throw new UnsupportedOperationException("unimplemented");
......
...@@ -20,3 +20,87 @@ select dateadd('year', -1, timestamp '2000-02-29 10:20:30.012345678') d1 from te ...@@ -20,3 +20,87 @@ select dateadd('year', -1, timestamp '2000-02-29 10:20:30.012345678') d1 from te
> ----------------------------- > -----------------------------
> 1999-02-28 10:20:30.012345678 > 1999-02-28 10:20:30.012345678
> rows: 1 > rows: 1
drop table test;
> ok
create table test(d date, t time, ts timestamp);
> ok
insert into test values(date '2001-01-01', time '01:00:00', timestamp '2010-01-01 00:00:00');
> update count: 1
select ts + t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t + t - t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t * 0.5 x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + 0.5 x from test;
> X
> ---------------------
> 2010-01-01 12:00:00.0
> rows: 1
select ts - 1.5 x from test;
> X
> ---------------------
> 2009-12-30 12:00:00.0
> rows: 1
select ts + 0.5 * t + t - t x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + t / 0.5 x from test;
> X
> ---------------------
> 2010-01-01 02:00:00.0
> rows: 1
select d + t, t + d - t x from test;
> T + D X
> --------------------- ---------------------
> 2001-01-01 01:00:00.0 2001-01-01 00:00:00.0
> rows: 1
select 1 + d + 1, d - 1, 2 + ts + 2, ts - 2 from test;
> DATEADD('DAY', 1, DATEADD('DAY', 1, D)) DATEADD('DAY', -1, D) DATEADD('DAY', 2, DATEADD('DAY', 2, TS)) DATEADD('DAY', -2, TS)
> --------------------------------------- --------------------- ---------------------------------------- ----------------------
> 2001-01-03 00:00:00.0 2000-12-31 00:00:00.0 2010-01-05 00:00:00.0 2009-12-30 00:00:00.0
> rows: 1
select 1 + d + t + 1 from test;
> DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D)))
> ---------------------------------------------
> 2001-01-03 01:00:00.0
> rows: 1
select ts - t - 2 from test;
> DATEADD('DAY', -2, (TS - T))
> ----------------------------
> 2009-12-29 23:00:00.0
> rows: 1
drop table test;
> ok
call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
> TIMESTAMP '2001-02-03 04:05:06.790001'
> --------------------------------------
> 2001-02-03 04:05:06.790001
> rows: 1
...@@ -93,3 +93,68 @@ select datediff('millisecond', timestamp '2004-01-01 10:00:00.5', timestamp '200 ...@@ -93,3 +93,68 @@ select datediff('millisecond', timestamp '2004-01-01 10:00:00.5', timestamp '200
> 500 > 500
> rows: 1 > rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.001', '1900-01-01 00:00:00.002'), DATEDIFF('SECOND', '2000-01-01 00:00:00.001', '2000-01-01 00:00:00.002');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.000', '1900-01-01 00:00:00.001'), DATEDIFF('SECOND', '2000-01-01 00:00:00.000', '2000-01-01 00:00:00.001');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:01.000', '1900-01-01 00:00:02.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:01.000', '2000-01-01 00:00:02.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.001', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.001', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.000', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.000', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.001', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.001', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
select datediff(day, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0'), datediff(wk, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0');
> 38 5
> -- -
> 38 5
> rows: 1
call datediff('MS', TIMESTAMP '2001-02-03 04:05:06.789001', TIMESTAMP '2001-02-03 04:05:06.789002');
> 0
> -
> 0
> rows: 1
call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 00:00:00.000');
> 3408134399000
> -------------
> 3408134399000
> rows: 1
...@@ -14,3 +14,22 @@ select dayofmonth(date '2005-09-12') d12 from test; ...@@ -14,3 +14,22 @@ select dayofmonth(date '2005-09-12') d12 from test;
> --- > ---
> 12 > 12
> rows: 1 > rows: 1
drop table test;
> ok
create table test(ts timestamp with time zone);
> ok
insert into test(ts) values ('2010-05-11 00:00:00+10:00'), ('2010-05-11 00:00:00-10:00');
> update count: 2
select dayofmonth(ts) d from test;
> D
> --
> 11
> 11
> rows: 2
drop table test;
> ok
...@@ -14,3 +14,22 @@ select hour(time '23:10:59') d23 from test; ...@@ -14,3 +14,22 @@ select hour(time '23:10:59') d23 from test;
> --- > ---
> 23 > 23
> rows: 1 > rows: 1
drop table test;
> ok
create table test(ts timestamp with time zone);
> ok
insert into test(ts) values ('2010-05-11 05:15:10+10:00'), ('2010-05-11 05:15:10-10:00');
> update count: 2
select hour(ts) h from test;
> H
> -
> 5
> 5
> rows: 2
drop table test;
> ok
...@@ -557,81 +557,6 @@ explain select * from test limit 10 sample_size 10; ...@@ -557,81 +557,6 @@ explain select * from test limit 10 sample_size 10;
drop table test; drop table test;
> ok > ok
create table test(d date, t time, ts timestamp);
> ok
insert into test values(date '2001-01-01', time '01:00:00', timestamp '2010-01-01 00:00:00');
> update count: 1
select ts + t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t + t - t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t * 0.5 x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + 0.5 x from test;
> X
> ---------------------
> 2010-01-01 12:00:00.0
> rows: 1
select ts - 1.5 x from test;
> X
> ---------------------
> 2009-12-30 12:00:00.0
> rows: 1
select ts + 0.5 * t + t - t x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + t / 0.5 x from test;
> X
> ---------------------
> 2010-01-01 02:00:00.0
> rows: 1
select d + t, t + d - t x from test;
> T + D X
> --------------------- ---------------------
> 2001-01-01 01:00:00.0 2001-01-01 00:00:00.0
> rows: 1
select 1 + d + 1, d - 1, 2 + ts + 2, ts - 2 from test;
> DATEADD('DAY', 1, DATEADD('DAY', 1, D)) DATEADD('DAY', -1, D) DATEADD('DAY', 2, DATEADD('DAY', 2, TS)) DATEADD('DAY', -2, TS)
> --------------------------------------- --------------------- ---------------------------------------- ----------------------
> 2001-01-03 00:00:00.0 2000-12-31 00:00:00.0 2010-01-05 00:00:00.0 2009-12-30 00:00:00.0
> rows: 1
select 1 + d + t + 1 from test;
> DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D)))
> ---------------------------------------------
> 2001-01-03 01:00:00.0
> rows: 1
select ts - t - 2 from test;
> DATEADD('DAY', -2, (TS - T))
> ----------------------------
> 2009-12-29 23:00:00.0
> rows: 1
drop table test;
> ok
create table test(id int primary key); create table test(id int primary key);
> ok > ok
...@@ -3904,60 +3829,6 @@ SELECT CASE WHEN NOT (false IN (null)) THEN false END; ...@@ -3904,60 +3829,6 @@ SELECT CASE WHEN NOT (false IN (null)) THEN false END;
> null > null
> rows: 1 > rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.001', '1900-01-01 00:00:00.002'), DATEDIFF('SECOND', '2000-01-01 00:00:00.001', '2000-01-01 00:00:00.002');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.000', '1900-01-01 00:00:00.001'), DATEDIFF('SECOND', '2000-01-01 00:00:00.000', '2000-01-01 00:00:00.001');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:01.000', '1900-01-01 00:00:02.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:01.000', '2000-01-01 00:00:02.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.001', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.001', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.000', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.000', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.001', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.001', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
select datediff(day, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0'), datediff(wk, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0');
> 38 5
> -- -
> 38 5
> rows: 1
create table test(id int); create table test(id int);
> ok > ok
...@@ -3972,30 +3843,12 @@ insert into test values(1), (2), (3), (4); ...@@ -3972,30 +3843,12 @@ insert into test values(1), (2), (3), (4);
drop table test; drop table test;
> ok > ok
call datediff('MS', TIMESTAMP '2001-02-03 04:05:06.789001', TIMESTAMP '2001-02-03 04:05:06.789002');
> 0
> -
> 0
> rows: 1
call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 00:00:00.000');
> 3408134399000
> -------------
> 3408134399000
> rows: 1
call select 1.0/3.0*3.0, 100.0/2.0, -25.0/100.0, 0.0/3.0, 6.9/2.0, 0.72179425150347250912311550800000 / 5314251955.21; call select 1.0/3.0*3.0, 100.0/2.0, -25.0/100.0, 0.0/3.0, 6.9/2.0, 0.72179425150347250912311550800000 / 5314251955.21;
> SELECT 0.999999999999999999999999990, 50, -0.25, 0, 3.45, 1.35822361752313607260107721120531135706133161972E-10 FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */ > SELECT 0.999999999999999999999999990, 50, -0.25, 0, 3.45, 1.35822361752313607260107721120531135706133161972E-10 FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> (0.999999999999999999999999990, 50, -0.25, 0, 3.45, 1.35822361752313607260107721120531135706133161972E-10) > (0.999999999999999999999999990, 50, -0.25, 0, 3.45, 1.35822361752313607260107721120531135706133161972E-10)
> rows: 1 > rows: 1
call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
> TIMESTAMP '2001-02-03 04:05:06.790001'
> --------------------------------------
> 2001-02-03 04:05:06.790001
> rows: 1
CALL 1 /* comment */ ;; CALL 1 /* comment */ ;;
> 1 > 1
> - > -
......
...@@ -5,21 +5,26 @@ ...@@ -5,21 +5,26 @@
*/ */
package org.h2.test.unit; package org.h2.test.unit;
import java.sql.Timestamp; import static org.h2.util.DateTimeUtils.getIsoDayOfWeek;
import java.text.ParseException; import static org.h2.util.DateTimeUtils.getIsoWeek;
import java.text.SimpleDateFormat; import static org.h2.util.DateTimeUtils.getIsoYear;
import java.util.Date;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.DateTimeUtils; import org.h2.value.Value;
import org.h2.value.ValueDate;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueTimestampTimeZone;
/** /**
* Test cases for DateTimeIso8601Utils. * Test cases for DateTimeIso8601Utils.
*/ */
public class TestDateIso8601 extends TestBase { public class TestDateIso8601 extends TestBase {
private final SimpleDateFormat dateFormatter = private enum Type {
new SimpleDateFormat("yyyy-MM-dd"); DATE, TIMESTAMP, TIMESTAMP_TIMEZONE_0, TIMESTAMP_TIMEZONE_PLUS_18, TIMESTAMP_TIMEZONE_MINUS_18;
}
private static Type type;
/** /**
* Run just this test. * Run just this test.
...@@ -30,8 +35,41 @@ public class TestDateIso8601 extends TestBase { ...@@ -30,8 +35,41 @@ public class TestDateIso8601 extends TestBase {
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
private static Value parse(String s) {
if (type == null) {
throw new IllegalStateException();
}
switch (type) {
case DATE:
return ValueDate.parse(s);
case TIMESTAMP:
return ValueTimestamp.parse(s);
case TIMESTAMP_TIMEZONE_0:
return ValueTimestampTimeZone.parse(s + " 00:00:00.0Z");
case TIMESTAMP_TIMEZONE_PLUS_18:
return ValueTimestampTimeZone.parse(s + " 00:00:00+18:00");
case TIMESTAMP_TIMEZONE_MINUS_18:
return ValueTimestampTimeZone.parse(s + " 00:00:00-18:00");
default:
throw new IllegalStateException();
}
}
@Override @Override
public void test() throws Exception { public void test() throws Exception {
type = Type.DATE;
doTest();
type = Type.TIMESTAMP;
doTest();
type = Type.TIMESTAMP_TIMEZONE_0;
doTest();
type = Type.TIMESTAMP_TIMEZONE_PLUS_18;
doTest();
type = Type.TIMESTAMP_TIMEZONE_MINUS_18;
doTest();
}
private void doTest() throws Exception {
testIsoDayOfWeek(); testIsoDayOfWeek();
testIsoWeekJanuary1thMonday(); testIsoWeekJanuary1thMonday();
testIsoWeekJanuary1thTuesday(); testIsoWeekJanuary1thTuesday();
...@@ -49,14 +87,6 @@ public class TestDateIso8601 extends TestBase { ...@@ -49,14 +87,6 @@ public class TestDateIso8601 extends TestBase {
testIsoYearJanuary1thSunday(); testIsoYearJanuary1thSunday();
} }
private Date parse(String s) throws ParseException {
return dateFormatter.parse(s);
}
private static int getIsoDayOfWeek(Date date) {
return DateTimeUtils.getIsoDayOfWeek(date);
}
/** /**
* Test if day of week is returned as Monday = 1 to Sunday = 7. * Test if day of week is returned as Monday = 1 to Sunday = 7.
*/ */
...@@ -70,11 +100,6 @@ public class TestDateIso8601 extends TestBase { ...@@ -70,11 +100,6 @@ public class TestDateIso8601 extends TestBase {
assertEquals(7, getIsoDayOfWeek(parse("2008-10-05"))); assertEquals(7, getIsoDayOfWeek(parse("2008-10-05")));
} }
private static int getIsoWeek(Date date) {
Timestamp ts = new Timestamp(date.getTime());
return DateTimeUtils.getIsoWeek(ts);
}
/** /**
* January 1st is a Monday therefore the week belongs to the next year. * January 1st is a Monday therefore the week belongs to the next year.
*/ */
...@@ -154,11 +179,6 @@ public class TestDateIso8601 extends TestBase { ...@@ -154,11 +179,6 @@ public class TestDateIso8601 extends TestBase {
assertEquals(2, getIsoWeek(parse("2012-01-09"))); assertEquals(2, getIsoWeek(parse("2012-01-09")));
} }
private static int getIsoYear(Date date) {
Timestamp ts = new Timestamp(date.getTime());
return DateTimeUtils.getIsoYear(ts);
}
/** /**
* January 1st is a Monday therefore year is equal to isoYear. * January 1st is a Monday therefore year is equal to isoYear.
*/ */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论