!1307 [171] Fix for to_unixtime() issue

Merge pull request !1307 from i-robot/pull170
This commit is contained in:
i-robot 2021-12-10 07:58:04 +00:00 committed by Gitee
commit da749d3827
6 changed files with 80 additions and 8 deletions

View File

@ -49,6 +49,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static io.prestosql.SystemSessionProperties.SNAPSHOT_ENABLED;
import static io.prestosql.SystemSessionProperties.TIME_ZONE_ID;
import static io.prestosql.spi.StandardErrorCode.NOT_FOUND;
import static io.prestosql.spi.connector.CatalogName.createInformationSchemaCatalogName;
import static io.prestosql.spi.connector.CatalogName.createSystemTablesCatalogName;
@ -197,7 +198,11 @@ public final class Session
public TimeZoneKey getTimeZoneKey()
{
return timeZoneKey;
String timeZoneId = getSystemProperty(TIME_ZONE_ID, String.class);
if (timeZoneId == null) {
return timeZoneKey;
}
return TimeZoneKey.getTimeZoneKey(timeZoneId);
}
public Locale getLocale()

View File

@ -22,6 +22,7 @@ import io.prestosql.memory.MemoryManagerConfig;
import io.prestosql.snapshot.SnapshotConfig;
import io.prestosql.spi.PrestoException;
import io.prestosql.spi.session.PropertyMetadata;
import io.prestosql.spi.type.TimeZoneKey;
import io.prestosql.sql.analyzer.FeaturesConfig;
import io.prestosql.sql.analyzer.FeaturesConfig.DynamicFilterDataType;
import io.prestosql.sql.analyzer.FeaturesConfig.JoinDistributionType;
@ -75,6 +76,7 @@ public final class SystemSessionProperties
public static final String QUERY_MAX_CPU_TIME = "query_max_cpu_time";
public static final String QUERY_MAX_STAGE_COUNT = "query_max_stage_count";
public static final String REDISTRIBUTE_WRITES = "redistribute_writes";
public static final String TIME_ZONE_ID = "time_zone_id";
// redistribute writes type session property key
public static final String REDISTRIBUTE_WRITES_TYPE = "redistribute_writes_type";
public static final String SCALE_WRITERS = "scale_writers";
@ -281,6 +283,16 @@ public final class SystemSessionProperties
"Force parallel distributed writes",
featuresConfig.isRedistributeWrites(),
false),
stringProperty(
TIME_ZONE_ID,
"Time Zone Id for the current session",
null,
value -> {
if (value != null) {
TimeZoneKey.getTimeZoneKey(value);
}
},
true),
// redistribute writes type config
enumProperty(
REDISTRIBUTE_WRITES_TYPE,

View File

@ -53,6 +53,7 @@ import static io.prestosql.spi.util.DateTimeZoneIndex.getDateTimeZone;
import static io.prestosql.spi.util.DateTimeZoneIndex.packDateTimeWithZone;
import static io.prestosql.spi.util.DateTimeZoneIndex.unpackChronology;
import static io.prestosql.type.DateTimeOperators.modulo24Hour;
import static io.prestosql.type.TimestampOperators.castToTimestampWithTimeZone;
import static io.prestosql.util.Failures.checkCondition;
import static java.lang.Math.toIntExact;
import static java.lang.String.format;
@ -175,16 +176,23 @@ public final class DateTimeFunctions
@ScalarFunction("to_unixtime")
@SqlType(StandardTypes.DOUBLE)
public static double toUnixTime(@SqlType(StandardTypes.TIMESTAMP) long timestamp)
public static double toUnixTime(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP) long timestamp)
{
return timestamp / 1000.0;
// Timestamp should use Session timezone
long timestampWithZone = castToTimestampWithTimeZone(session, timestamp);
return unpackMillisUtc(timestampWithZone) / 1000.0;
}
@ScalarFunction("to_unixtime")
@SqlType(StandardTypes.DOUBLE)
public static double toUnixTimeFromTimestampWithTimeZone(@SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) long timestampWithTimeZone)
public static double toUnixTimeFromTimestampWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) long timestampWithTimeZone)
{
return unpackMillisUtc(timestampWithTimeZone) / 1000.0;
ISOChronology localChronology = getChronology(session.getTimeZoneKey());
long localMillis = localChronology.getZone().convertUTCToLocal(unpackMillisUtc(timestampWithTimeZone));
ISOChronology zoneChronology = unpackChronology(timestampWithTimeZone);
long zoneMillis = zoneChronology.getZone().convertLocalToUTC(localMillis, false);
return zoneMillis / 1000.0;
}
@ScalarFunction("to_iso8601")

View File

@ -28,6 +28,7 @@ import io.prestosql.spi.function.SqlNullable;
import io.prestosql.spi.function.SqlType;
import io.prestosql.spi.type.AbstractLongType;
import io.prestosql.spi.type.StandardTypes;
import io.prestosql.spi.type.TimeZoneKey;
import org.joda.time.chrono.ISOChronology;
import java.util.concurrent.TimeUnit;
@ -149,11 +150,12 @@ public final class TimestampOperators
@SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE)
public static long castToTimestampWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP) long value)
{
ISOChronology localChronology = getChronology(session.getTimeZoneKey());
TimeZoneKey timeZoneKey = session.getTimeZoneKey();
ISOChronology localChronology = getChronology(timeZoneKey);
// This cast does treat TIMESTAMP as wall time in session TZ. This means that in order to get
// its UTC representation we need to shift the value by the offset of TZ.
return packDateTimeWithZone(localChronology.getZone().convertLocalToUTC(value, false), session.getTimeZoneKey());
return packDateTimeWithZone(localChronology.getZone().convertLocalToUTC(value, false), timeZoneKey);
}
@ScalarOperator(CAST)

View File

@ -29,6 +29,8 @@ import java.time.LocalTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import static io.prestosql.SystemSessionProperties.TIME_ZONE_ID;
import static io.prestosql.spi.type.DoubleType.DOUBLE;
import static io.prestosql.spi.type.TimeWithTimeZoneType.TIME_WITH_TIME_ZONE;
import static io.prestosql.spi.type.TimeZoneKey.UTC_KEY;
import static io.prestosql.spi.type.TimeZoneKey.getTimeZoneKey;
@ -139,4 +141,37 @@ public class TestDateTimeFunctions
localAssertion.assertFunctionString("NOW()", TIMESTAMP_WITH_TIME_ZONE, "2017-03-01 14:30:00.000 " + DATE_TIME_ZONE.getID());
}
}
@Test
public void testToUnixtime()
{
assertFunction("to_unixtime(TIMESTAMP'2021-07-25 17:10:00')", DOUBLE, 1.6271862E9);
String timeZoneId = "Asia/Shanghai";
Session localSession = Session.builder(session)
.setSystemProperty(TIME_ZONE_ID, timeZoneId)
.build();
try (FunctionAssertions localAssertion = new FunctionAssertions(localSession)) {
localAssertion.assertFunction("to_unixtime(TIMESTAMP'2021-07-25 17:10:00')", DOUBLE, 1.6272042E9);
}
assertFunction(String.format("to_unixtime(at_timezone(timestamp'2021-07-25 17:10:00', '%s'))", timeZoneId), DOUBLE, 1.6272042E9);
timeZoneId = "Europe/London";
localSession = Session.builder(session)
.setSystemProperty(TIME_ZONE_ID, timeZoneId)
.build();
try (FunctionAssertions localAssertion = new FunctionAssertions(localSession)) {
localAssertion.assertFunction("to_unixtime(TIMESTAMP'2021-07-25 17:10:00')", DOUBLE, 1.6272294E9);
}
assertFunction(String.format("to_unixtime(at_timezone(timestamp'2021-07-25 17:10:00', '%s'))", timeZoneId), DOUBLE, 1.6272294E9);
timeZoneId = "America/New_York";
localSession = Session.builder(session)
.setSystemProperty(TIME_ZONE_ID, timeZoneId)
.build();
try (FunctionAssertions localAssertion = new FunctionAssertions(localSession)) {
localAssertion.assertFunction("to_unixtime(TIMESTAMP'2021-07-25 17:10:00')", DOUBLE, 1.6272474E9);
}
assertFunction(String.format("to_unixtime(at_timezone(timestamp'2021-07-25 17:10:00', '%s'))", timeZoneId), DOUBLE, 1.6272474E9);
}
}

View File

@ -18,6 +18,7 @@ import io.airlift.units.Duration;
import io.prestosql.spi.type.Type;
import java.util.EnumSet;
import java.util.function.Consumer;
import java.util.function.Function;
import static io.prestosql.spi.type.BigintType.BIGINT;
@ -193,6 +194,11 @@ public final class PropertyMetadata<T>
}
public static PropertyMetadata<String> stringProperty(String name, String description, String defaultValue, boolean hidden)
{
return stringProperty(name, description, defaultValue, value -> {}, hidden);
}
public static PropertyMetadata<String> stringProperty(String name, String description, String defaultValue, Consumer<String> validation, boolean hidden)
{
return new PropertyMetadata<>(
name,
@ -201,7 +207,11 @@ public final class PropertyMetadata<T>
String.class,
defaultValue,
hidden,
String.class::cast,
object -> {
String value = (String) object;
validation.accept(value);
return value;
},
object -> object);
}