Skip to content

Commit

Permalink
Add CAST TIMESTAMP WITH TIME ZONE to and from TIMESTAMP (#6529)
Browse files Browse the repository at this point in the history
Summary:
Presto also allows CAST TIMESTAMP WITH TIME ZONE to and from DATE and VARCHAR.
This functionality is not available yet.

Pull Request resolved: #6529

Reviewed By: mbasmanova

Differential Revision: D49196796

Pulled By: zacw7

fbshipit-source-id: 57dff733fda2320c1f7ee2a09a35d8ea7823fa8f
  • Loading branch information
zacw7 authored and facebook-github-bot committed Sep 14, 2023
1 parent b56ad89 commit e9354bb
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 6 deletions.
87 changes: 84 additions & 3 deletions velox/docs/functions/presto/conversion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ are supported if the conversion of their element types are supported. In additio
supported conversions to/from JSON are listed in :doc:`json`.

.. list-table::
:widths: 25 25 25 25 25 25 25 25 25 25 25 25
:widths: 25 25 25 25 25 25 25 25 25 25 25 25 25
:header-rows: 1

* -
Expand All @@ -43,6 +43,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- double
- varchar
- timestamp
- timestamp with time zone
- date
- decimal
* - tinyint
Expand All @@ -56,6 +57,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- Y
-
-
-
- Y
* - smallint
- Y
Expand All @@ -68,6 +70,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- Y
-
-
-
- Y
* - integer
- Y
Expand All @@ -80,6 +83,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- Y
-
-
-
- Y
* - bigint
- Y
Expand All @@ -92,6 +96,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- Y
-
-
-
- Y
* - boolean
- Y
Expand All @@ -105,6 +110,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - real
- Y
- Y
Expand All @@ -117,6 +123,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - double
- Y
- Y
Expand All @@ -129,6 +136,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - varchar
- Y
- Y
Expand All @@ -139,6 +147,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- Y
- Y
- Y
-
- Y
-
* - timestamp
Expand All @@ -150,9 +159,23 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
- Y
- Y
- Y
- Y
-
* - timestamp with time zone
-
-
-
-
-
-
-
-
- Y
- Y
-
-
* - date
-
-
Expand All @@ -165,6 +188,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- Y
-
-
-
* - decimal
- Y
- Y
Expand All @@ -176,6 +200,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
- Y

Cast to Integral Types
Expand Down Expand Up @@ -458,7 +483,7 @@ Valid examples
SELECT cast(true as varchar); -- 'true'
SELECT cast(timestamp '1970-01-01 00:00:00' as varchar); -- '1970-01-01T00:00:00.000'

Cast to Timestamp
Cast to TIMESTAMP
-----------------

From strings
Expand Down Expand Up @@ -495,6 +520,62 @@ Valid examples
SELECT cast(date '1970-01-01' as timestamp); -- 1970-01-01 00:00:00
SELECT cast(date '2012-03-09' as timestamp); -- 2012-03-09 00:00:00

From TIMESTAMP WITH TIME ZONE
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The results depend on whether configuration property `adjust_timestamp_to_session_timezone` is set or not.

If set to true, input timezone is ignored and timestamp is returned as is. For example,
"1970-01-01 00:00:00.000 America/Los_Angeles" becomes "1970-01-01 00:00:00.000".

Otherwise, timestamp is shifted by the offset of the timezone. For example,
"1970-01-01 00:00:00.000 America/Los_Angeles" becomes "1969-12-31 16:00:00.000".

Valid examples

::

-- `adjust_timestamp_to_session_timezone` is true
SELECT cast(timestamp '1970-01-01 00:00:00 America/Los_Angeles' as timestamp); -- 1970-01-01 00:00:00.000
SELECT cast(timestamp '2012-03-09 10:00:00 Asia/Chongqing' as timestamp); -- 2012-03-09 10:00:00.000
SELECT cast(from_unixtime(0, '+06:00') as timestamp); -- 1970-01-01 00:00:00.000
SELECT cast(from_unixtime(0, '-02:00') as timestamp); -- 1970-01-01 00:00:00.000

-- `adjust_timestamp_to_session_timezone` is false
SELECT cast(timestamp '1970-01-01 00:00:00 America/Los_Angeles' as timestamp); -- 1969-12-31 16:00:00.000
SELECT cast(timestamp '2012-03-09 10:00:00 Asia/Chongqing' as timestamp); -- 2012-03-09 18:00:00.000
SELECT cast(from_unixtime(0, '+06:00') as timestamp); -- 1970-01-01 06:00:00.000
SELECT cast(from_unixtime(0, '-02:00') as timestamp); -- 1969-12-31 22:00:00.000

Cast to TIMESTAMP WITH TIME ZONE
--------------------------------

From TIMESTAMP
^^^^^^^^^^^^^^

The results depend on whether configuration property `adjust_timestamp_to_session_timezone` is set or not.

If set to true, the output is adjusted to be equivalent as the input timestamp in UTC
based on the user provided `session_timezone` (if any). For example, when user supplies
"America/Los_Angeles" "1970-01-01 00:00:00.000" becomes "1969-12-31 16:00:00.000 America/Los_Angeles".

Otherwise, the user provided `session_timezone` (if any) is simply appended to the input
timestamp. For example, "1970-01-01 00:00:00.000" becomes "1970-01-01 00:00:00.000 America/Los_Angeles".

Valid examples

::

-- `adjust_timestamp_to_session_timezone` is true
SELECT cast(timestamp '1970-01-01 00:00:00' as timestamp with time zone); -- 1969-12-31 16:00:00.000 America/Los_Angeles
SELECT cast(timestamp '2012-03-09 10:00:00' as timestamp with time zone); -- 2012-03-09 02:00:00.000 America/Los_Angeles
SELECT cast(from_unixtime(0) as timestamp with time zone); -- 1969-12-31 16:00:00.000 America/Los_Angeles

-- `adjust_timestamp_to_session_timezone` is false
SELECT cast(timestamp '1970-01-01 00:00:00' as timestamp with time zone); -- 1970-01-01 00:00:00.000 America/Los_Angeles
SELECT cast(timestamp '2012-03-09 10:00:00' as timestamp with time zone); -- 2012-03-09 10:00:00.000 America/Los_Angeles
SELECT cast(from_unixtime(0) as timestamp with time zone); -- 1970-01-01 00:00:00.000 America/Los_Angeles

Cast to Date
------------

Expand All @@ -516,7 +597,7 @@ Invalid example

SELECT cast('2012-Oct-23' as date); -- Invalid argument

From timestamp
From TIMESTAMP
^^^^^^^^^^^^^^

Casting from timestamp to date is allowed. If present, the part of `hh:mm:ss`
Expand Down
1 change: 1 addition & 0 deletions velox/functions/prestosql/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ add_executable(
SplitTest.cpp
SplitToMapTest.cpp
StringFunctionsTest.cpp
TimestampWithTimeZoneCastTest.cpp
TransformTest.cpp
TransformKeysTest.cpp
TransformValuesTest.cpp
Expand Down
61 changes: 61 additions & 0 deletions velox/functions/prestosql/tests/TimestampWithTimeZoneCastTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "velox/functions/prestosql/tests/CastBaseTest.h"
#include "velox/functions/prestosql/types/TimestampWithTimeZoneType.h"

using namespace facebook::velox;

class TimestampWithTimeZoneCastTest : public functions::test::CastBaseTest {
public:
RowVectorPtr makeTimestampWithTimeZoneVector(
const VectorPtr& timestamps,
const VectorPtr& timezones) {
VELOX_CHECK_EQ(timestamps->size(), timezones->size());
return std::make_shared<RowVector>(
pool(),
TIMESTAMP_WITH_TIME_ZONE(),
nullptr,
timestamps->size(),
std::vector<VectorPtr>({timestamps, timezones}));
}
};

TEST_F(TimestampWithTimeZoneCastTest, fromTimestamp) {
const auto tsVector = makeNullableFlatVector<Timestamp>(
{Timestamp(1996, 0), std::nullopt, Timestamp(19920, 0)});
const auto expected = makeTimestampWithTimeZoneVector(
makeFlatVector<int64_t>(
{1996 * kMillisInSecond, 0, 19920 * kMillisInSecond}),
makeFlatVector<int16_t>({0, 0, 0}));
expected->setNull(1, true);

testCast<ComplexType>(
TIMESTAMP(), TIMESTAMP_WITH_TIME_ZONE(), tsVector, expected);
}

TEST_F(TimestampWithTimeZoneCastTest, toTimestamp) {
const auto tsWithTZVector = makeTimestampWithTimeZoneVector(
makeFlatVector<int64_t>(
{1996 * kMillisInSecond, 0, 19920 * kMillisInSecond}),
makeFlatVector<int16_t>({0, 0, 1825 /*America/Los_Angeles*/}));
tsWithTZVector->setNull(1, true);
const auto expected = makeNullableFlatVector<Timestamp>(
{Timestamp(1996, 0), std::nullopt, Timestamp(19920 - 8 * 3600, 0)});

testCast<ComplexType>(
TIMESTAMP_WITH_TIME_ZONE(), TIMESTAMP(), tsWithTZVector, expected);
}
Loading

0 comments on commit e9354bb

Please sign in to comment.