提交 134712c8 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Move date-time formatting code to DateTimeUtils and reuse them in TimestampWithTimeZone

上级 cad0c35a
...@@ -7,7 +7,6 @@ package org.h2.api; ...@@ -7,7 +7,6 @@ package org.h2.api;
import java.io.Serializable; import java.io.Serializable;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/** /**
* How we expose "TIMESTAMP WITH TIMEZONE" in our ResultSets. * How we expose "TIMESTAMP WITH TIMEZONE" in our ResultSets.
...@@ -110,62 +109,7 @@ public class TimestampWithTimeZone implements Serializable, Cloneable { ...@@ -110,62 +109,7 @@ public class TimestampWithTimeZone implements Serializable, Cloneable {
@Override @Override
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); return DateTimeUtils.timestampTimeZoneToString(dateValue, timeNanos, timeZoneOffsetMins);
int y = DateTimeUtils.yearFromDateValue(dateValue);
int month = DateTimeUtils.monthFromDateValue(dateValue);
int d = DateTimeUtils.dayFromDateValue(dateValue);
if (y > 0 && y < 10000) {
StringUtils.appendZeroPadded(buff, 4, y);
} else {
buff.append(y);
}
buff.append('-');
StringUtils.appendZeroPadded(buff, 2, month);
buff.append('-');
StringUtils.appendZeroPadded(buff, 2, d);
buff.append(' ');
long nanos = timeNanos;
long ms = nanos / 1000000;
nanos -= ms * 1000000;
long s = ms / 1000;
ms -= s * 1000;
long min = s / 60;
s -= min * 60;
long h = min / 60;
min -= h * 60;
StringUtils.appendZeroPadded(buff, 2, h);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, min);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, s);
buff.append('.');
int start = buff.length();
StringUtils.appendZeroPadded(buff, 3, ms);
if (nanos > 0) {
StringUtils.appendZeroPadded(buff, 6, nanos);
}
for (int i = buff.length() - 1; i > start; i--) {
if (buff.charAt(i) != '0') {
break;
}
buff.deleteCharAt(i);
}
short tz = timeZoneOffsetMins;
if (tz < 0) {
buff.append('-');
tz = (short) -tz;
} else {
buff.append('+');
}
int hours = tz / 60;
tz -= hours * 60;
int mins = tz;
StringUtils.appendZeroPadded(buff, 2, hours);
if (mins != 0) {
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, mins);
}
return buff.toString();
} }
@Override @Override
......
...@@ -999,4 +999,113 @@ public class DateTimeUtils { ...@@ -999,4 +999,113 @@ public class DateTimeUtils {
return resultDate; return resultDate;
} }
/**
* Append a date to the string builder.
*
* @param buff the target string builder
* @param dateValue the date value
*/
public static void appendDate(StringBuilder buff, long dateValue) {
int y = yearFromDateValue(dateValue);
int m = monthFromDateValue(dateValue);
int d = dayFromDateValue(dateValue);
if (y > 0 && y < 10000) {
StringUtils.appendZeroPadded(buff, 4, y);
} else {
buff.append(y);
}
buff.append('-');
StringUtils.appendZeroPadded(buff, 2, m);
buff.append('-');
StringUtils.appendZeroPadded(buff, 2, d);
}
/**
* Append a time to the string builder.
*
* @param buff the target string builder
* @param nanos the time in nanoseconds
* @param alwaysAddMillis whether to always add at least ".0"
*/
public static void appendTime(StringBuilder buff, long nanos,
boolean alwaysAddMillis) {
if (nanos < 0) {
buff.append('-');
nanos = -nanos;
}
/*
* nanos now either in range from 0 to Long.MAX_VALUE or equals to
* Long.MIN_VALUE. We need to divide nanos by 1000000 with unsigned division to
* get correct result. The simplest way to do this with such constraints is to
* divide -nanos by -1000000.
*/
long ms = -nanos / -1000000;
nanos -= ms * 1000000;
long s = ms / 1000;
ms -= s * 1000;
long m = s / 60;
s -= m * 60;
long h = m / 60;
m -= h * 60;
StringUtils.appendZeroPadded(buff, 2, h);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, m);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, s);
if (alwaysAddMillis || ms > 0 || nanos > 0) {
buff.append('.');
int start = buff.length();
StringUtils.appendZeroPadded(buff, 3, ms);
if (nanos > 0) {
StringUtils.appendZeroPadded(buff, 6, nanos);
}
for (int i = buff.length() - 1; i > start; i--) {
if (buff.charAt(i) != '0') {
break;
}
buff.deleteCharAt(i);
}
}
}
/**
* Append a time zone to the string builder.
*
* @param buff the target string builder
* @param tz the time zone in minutes
*/
public static void appendTimeZone(StringBuilder buff, short tz) {
if (tz < 0) {
buff.append('-');
tz = (short) -tz;
} else {
buff.append('+');
}
int hours = tz / 60;
tz -= hours * 60;
int mins = tz;
StringUtils.appendZeroPadded(buff, 2, hours);
if (mins != 0) {
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, mins);
}
}
/**
* Formats timestamp with time zone as string.
*
* @param dateValue the year-month-day bit field
* @param timeNanos nanoseconds since midnight
* @param timeZoneOffsetMins the time zone offset in minutes
* @return formatted string
*/
public static String timestampTimeZoneToString(long dateValue, long timeNanos, short timeZoneOffsetMins) {
StringBuilder buff = new StringBuilder(ValueTimestampTimeZone.DISPLAY_SIZE);
appendDate(buff, dateValue);
buff.append(' ');
appendTime(buff, timeNanos, true);
appendTimeZone(buff, timeZoneOffsetMins);
return buff.toString();
}
} }
...@@ -12,7 +12,6 @@ import java.sql.SQLException; ...@@ -12,7 +12,6 @@ import java.sql.SQLException;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/** /**
* Implementation of the DATE data type. * Implementation of the DATE data type.
...@@ -99,7 +98,7 @@ public class ValueDate extends Value { ...@@ -99,7 +98,7 @@ public class ValueDate extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
appendDate(buff, dateValue); DateTimeUtils.appendDate(buff, dateValue);
return buff.toString(); return buff.toString();
} }
...@@ -148,25 +147,4 @@ public class ValueDate extends Value { ...@@ -148,25 +147,4 @@ public class ValueDate extends Value {
prep.setDate(parameterIndex, getDate()); prep.setDate(parameterIndex, getDate());
} }
/**
* Append a date to the string builder.
*
* @param buff the target string builder
* @param dateValue the date value
*/
static void appendDate(StringBuilder buff, long dateValue) {
int y = DateTimeUtils.yearFromDateValue(dateValue);
int m = DateTimeUtils.monthFromDateValue(dateValue);
int d = DateTimeUtils.dayFromDateValue(dateValue);
if (y > 0 && y < 10000) {
StringUtils.appendZeroPadded(buff, 4, y);
} else {
buff.append(y);
}
buff.append('-');
StringUtils.appendZeroPadded(buff, 2, m);
buff.append('-');
StringUtils.appendZeroPadded(buff, 2, d);
}
} }
...@@ -12,7 +12,6 @@ import org.h2.api.ErrorCode; ...@@ -12,7 +12,6 @@ import org.h2.api.ErrorCode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/** /**
* Implementation of the TIME data type. * Implementation of the TIME data type.
...@@ -52,7 +51,7 @@ public class ValueTime extends Value { ...@@ -52,7 +51,7 @@ public class ValueTime extends Value {
if (!SysProperties.UNLIMITED_TIME_RANGE) { if (!SysProperties.UNLIMITED_TIME_RANGE) {
if (nanos < 0L || nanos >= 86400000000000L) { if (nanos < 0L || nanos >= 86400000000000L) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
appendTime(builder, nanos, false); DateTimeUtils.appendTime(builder, nanos, false);
throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2, throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2,
"TIME", builder.toString()); "TIME", builder.toString());
} }
...@@ -116,7 +115,7 @@ public class ValueTime extends Value { ...@@ -116,7 +115,7 @@ public class ValueTime extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
appendTime(buff, nanos, false); DateTimeUtils.appendTime(buff, nanos, false);
return buff.toString(); return buff.toString();
} }
...@@ -196,52 +195,4 @@ public class ValueTime extends Value { ...@@ -196,52 +195,4 @@ public class ValueTime extends Value {
return ValueTime.fromNanos(-nanos); return ValueTime.fromNanos(-nanos);
} }
/**
* Append a time to the string builder.
*
* @param buff the target string builder
* @param nanos the time in nanoseconds
* @param alwaysAddMillis whether to always add at least ".0"
*/
static void appendTime(StringBuilder buff, long nanos,
boolean alwaysAddMillis) {
if (nanos < 0) {
buff.append('-');
nanos = -nanos;
}
/*
* nanos now either in range from 0 to Long.MAX_VALUE or equals to
* Long.MIN_VALUE. We need to divide nanos by 1000000 with unsigned division to
* get correct result. The simplest way to do this with such constraints is to
* divide -nanos by -1000000.
*/
long ms = -nanos / -1000000;
nanos -= ms * 1000000;
long s = ms / 1000;
ms -= s * 1000;
long m = s / 60;
s -= m * 60;
long h = m / 60;
m -= h * 60;
StringUtils.appendZeroPadded(buff, 2, h);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, m);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, s);
if (alwaysAddMillis || ms > 0 || nanos > 0) {
buff.append('.');
int start = buff.length();
StringUtils.appendZeroPadded(buff, 3, ms);
if (nanos > 0) {
StringUtils.appendZeroPadded(buff, 6, nanos);
}
for (int i = buff.length() - 1; i > start; i--) {
if (buff.charAt(i) != '0') {
break;
}
buff.deleteCharAt(i);
}
}
}
} }
...@@ -259,9 +259,9 @@ public class ValueTimestamp extends Value { ...@@ -259,9 +259,9 @@ public class ValueTimestamp extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
ValueDate.appendDate(buff, dateValue); DateTimeUtils.appendDate(buff, dateValue);
buff.append(' '); buff.append(' ');
ValueTime.appendTime(buff, timeNanos, true); DateTimeUtils.appendTime(buff, timeNanos, true);
return buff.toString(); return buff.toString();
} }
......
...@@ -15,7 +15,6 @@ import org.h2.api.ErrorCode; ...@@ -15,7 +15,6 @@ import org.h2.api.ErrorCode;
import org.h2.api.TimestampWithTimeZone; import org.h2.api.TimestampWithTimeZone;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/** /**
* Implementation of the TIMESTAMP WITH TIME ZONE data type. * Implementation of the TIMESTAMP WITH TIME ZONE data type.
...@@ -34,7 +33,7 @@ public class ValueTimestampTimeZone extends Value { ...@@ -34,7 +33,7 @@ public class ValueTimestampTimeZone extends Value {
* The display size of the textual representation of a timestamp. Example: * The display size of the textual representation of a timestamp. Example:
* 2001-01-01 23:59:59.000 +10:00 * 2001-01-01 23:59:59.000 +10:00
*/ */
static final int DISPLAY_SIZE = 30; public static final int DISPLAY_SIZE = 30;
/** /**
* The default scale for timestamps. * The default scale for timestamps.
...@@ -233,35 +232,7 @@ public class ValueTimestampTimeZone extends Value { ...@@ -233,35 +232,7 @@ public class ValueTimestampTimeZone extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); return DateTimeUtils.timestampTimeZoneToString(dateValue, timeNanos, timeZoneOffsetMins);
ValueDate.appendDate(buff, dateValue);
buff.append(' ');
ValueTime.appendTime(buff, timeNanos, true);
appendTimeZone(buff, timeZoneOffsetMins);
return buff.toString();
}
/**
* Append a time zone to the string builder.
*
* @param buff the target string builder
* @param tz the time zone in minutes
*/
private static void appendTimeZone(StringBuilder buff, short tz) {
if (tz < 0) {
buff.append('-');
tz = (short) -tz;
} else {
buff.append('+');
}
int hours = tz / 60;
tz -= hours * 60;
int mins = tz;
StringUtils.appendZeroPadded(buff, 2, hours);
if (mins != 0) {
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, mins);
}
} }
@Override @Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论