提交 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;
import java.io.Serializable;
import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/**
* How we expose "TIMESTAMP WITH TIMEZONE" in our ResultSets.
......@@ -110,62 +109,7 @@ public class TimestampWithTimeZone implements Serializable, Cloneable {
@Override
public String toString() {
StringBuilder buff = new StringBuilder();
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();
return DateTimeUtils.timestampTimeZoneToString(dateValue, timeNanos, timeZoneOffsetMins);
}
@Override
......
......@@ -999,4 +999,113 @@ public class DateTimeUtils {
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;
import org.h2.api.ErrorCode;
import org.h2.message.DbException;
import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/**
* Implementation of the DATE data type.
......@@ -99,7 +98,7 @@ public class ValueDate extends Value {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
appendDate(buff, dateValue);
DateTimeUtils.appendDate(buff, dateValue);
return buff.toString();
}
......@@ -148,25 +147,4 @@ public class ValueDate extends Value {
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;
import org.h2.engine.SysProperties;
import org.h2.message.DbException;
import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/**
* Implementation of the TIME data type.
......@@ -52,7 +51,7 @@ public class ValueTime extends Value {
if (!SysProperties.UNLIMITED_TIME_RANGE) {
if (nanos < 0L || nanos >= 86400000000000L) {
StringBuilder builder = new StringBuilder();
appendTime(builder, nanos, false);
DateTimeUtils.appendTime(builder, nanos, false);
throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2,
"TIME", builder.toString());
}
......@@ -116,7 +115,7 @@ public class ValueTime extends Value {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
appendTime(buff, nanos, false);
DateTimeUtils.appendTime(buff, nanos, false);
return buff.toString();
}
......@@ -196,52 +195,4 @@ public class ValueTime extends Value {
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 {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
ValueDate.appendDate(buff, dateValue);
DateTimeUtils.appendDate(buff, dateValue);
buff.append(' ');
ValueTime.appendTime(buff, timeNanos, true);
DateTimeUtils.appendTime(buff, timeNanos, true);
return buff.toString();
}
......
......@@ -15,7 +15,6 @@ import org.h2.api.ErrorCode;
import org.h2.api.TimestampWithTimeZone;
import org.h2.message.DbException;
import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils;
/**
* Implementation of the TIMESTAMP WITH TIME ZONE data type.
......@@ -34,7 +33,7 @@ public class ValueTimestampTimeZone extends Value {
* The display size of the textual representation of a timestamp. Example:
* 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.
......@@ -233,35 +232,7 @@ public class ValueTimestampTimeZone extends Value {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
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);
}
return DateTimeUtils.timestampTimeZoneToString(dateValue, timeNanos, timeZoneOffsetMins);
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论