blob: e012172109db9c539a4ef7bc8cf600aa5f151a82 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "paimon/common/utils/date_time_utils.h"
#include <memory>
#include "gtest/gtest.h"
#include "paimon/testing/utils/testharness.h"
#include "paimon/testing/utils/timezone_guard.h"
namespace paimon::test {
TEST(DateTimeUtilsTest, TestTimestampConverter) {
{
auto ret = DateTimeUtils::TimestampConverter(
10L, DateTimeUtils::SECOND, DateTimeUtils::MILLISECOND, DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(10000L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(
10L, DateTimeUtils::SECOND, DateTimeUtils::NANOSECOND, DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(10000000000L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(
10L, DateTimeUtils::SECOND, DateTimeUtils::NANOSECOND, DateTimeUtils::SECOND);
ASSERT_EQ(ret, std::make_pair(10000000000L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(
2567L, DateTimeUtils::MILLISECOND, DateTimeUtils::SECOND, DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(2L, 567000000L));
}
{
auto ret = DateTimeUtils::TimestampConverter(2567L, DateTimeUtils::MILLISECOND,
DateTimeUtils::SECOND, DateTimeUtils::SECOND);
ASSERT_EQ(ret, std::make_pair(2L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(
2567L, DateTimeUtils::MILLISECOND, DateTimeUtils::MICROSECOND, DateTimeUtils::SECOND);
ASSERT_EQ(ret, std::make_pair(2567000L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(2567L, DateTimeUtils::MILLISECOND,
DateTimeUtils::MICROSECOND,
DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(2567000L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(12345678L, DateTimeUtils::NANOSECOND,
DateTimeUtils::MILLISECOND,
DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(12L, 345678L));
}
{
auto ret = DateTimeUtils::TimestampConverter(12345678L, DateTimeUtils::NANOSECOND,
DateTimeUtils::MILLISECOND,
DateTimeUtils::MICROSECOND);
ASSERT_EQ(ret, std::make_pair(12L, 345L));
}
{
auto ret =
DateTimeUtils::TimestampConverter(12345678L, DateTimeUtils::NANOSECOND,
DateTimeUtils::MILLISECOND, DateTimeUtils::SECOND);
ASSERT_EQ(ret, std::make_pair(12L, 0L));
}
{
auto ret = DateTimeUtils::TimestampConverter(
-2240521239998998999L, DateTimeUtils::NANOSECOND, DateTimeUtils::MILLISECOND,
DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(-2240521239999L, 1001L));
}
{
// 9999-12-31
auto ret = DateTimeUtils::TimestampConverter(253402252995L, DateTimeUtils::SECOND,
DateTimeUtils::MILLISECOND,
DateTimeUtils::NANOSECOND);
ASSERT_EQ(ret, std::make_pair(253402252995000L, 0L));
}
}
TEST(DateTimeUtilsTest, TestTimestampToInteger) {
{
ASSERT_EQ(DateTimeUtils::TimestampToInteger(Timestamp(1758173447000l, 0),
/*dst_type=*/DateTimeUtils::TimeType::SECOND),
1758173447l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(1758173447001l, 0),
/*dst_type=*/DateTimeUtils::TimeType::MILLISECOND),
1758173447001l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(1758173447001l, 1000),
/*dst_type=*/DateTimeUtils::TimeType::MICROSECOND),
1758173447001001l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(1758173447001l, 1001),
/*dst_type=*/DateTimeUtils::TimeType::NANOSECOND),
1758173447001001001l);
}
{
ASSERT_EQ(DateTimeUtils::TimestampToInteger(Timestamp(-2493033748000l, 0),
/*dst_type=*/DateTimeUtils::TimeType::SECOND),
-2493033748l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(-2493033748001l, 0),
/*dst_type=*/DateTimeUtils::TimeType::MILLISECOND),
-2493033748001l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(-2493033748001l, 1000),
/*dst_type=*/DateTimeUtils::TimeType::MICROSECOND),
-2493033748000999l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(-2493033748001l, 1001),
/*dst_type=*/DateTimeUtils::TimeType::NANOSECOND),
-2493033748000998999l);
}
{
// 9999-12-31, cannot convert to nano second, which is overflow for int64
ASSERT_EQ(DateTimeUtils::TimestampToInteger(Timestamp(253402252995000l, 0),
/*dst_type=*/DateTimeUtils::TimeType::SECOND),
253402252995l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(253402252995001l, 0),
/*dst_type=*/DateTimeUtils::TimeType::MILLISECOND),
253402252995001l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(253402252995001l, 1000),
/*dst_type=*/DateTimeUtils::TimeType::MICROSECOND),
253402252995001001l);
}
{
// 0000-01-01, cannot convert to nano second, which is overflow for int64
ASSERT_EQ(DateTimeUtils::TimestampToInteger(Timestamp(-62167219200000l, 0),
/*dst_type=*/DateTimeUtils::TimeType::SECOND),
-62167219200l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(-62167219200000l, 0),
/*dst_type=*/DateTimeUtils::TimeType::MILLISECOND),
-62167219200000l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(-62167219200000l, 1000),
/*dst_type=*/DateTimeUtils::TimeType::MICROSECOND),
-62167219199999999l);
}
{
// test precision loss
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(1758173447001l, 1001),
/*dst_type=*/DateTimeUtils::TimeType::MICROSECOND),
1758173447001001l);
ASSERT_EQ(
DateTimeUtils::TimestampToInteger(Timestamp(1758173447001l, 1001),
/*dst_type=*/DateTimeUtils::TimeType::MILLISECOND),
1758173447001l);
ASSERT_EQ(DateTimeUtils::TimestampToInteger(Timestamp(1758173447001l, 1001),
/*dst_type=*/DateTimeUtils::TimeType::SECOND),
1758173447l);
}
}
TEST(DateTimeUtilsTest, TestGetPrecisionFromType) {
auto ts_sec_type = arrow::timestamp(arrow::TimeUnit::type::SECOND);
auto ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_sec_type);
ASSERT_EQ(DateTimeUtils::GetPrecisionFromType(ts_type), 0);
auto ts_milli_type = arrow::timestamp(arrow::TimeUnit::type::MILLI);
ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_milli_type);
ASSERT_EQ(DateTimeUtils::GetPrecisionFromType(ts_type), 3);
auto ts_micro_type = arrow::timestamp(arrow::TimeUnit::type::MICRO);
ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_micro_type);
ASSERT_EQ(DateTimeUtils::GetPrecisionFromType(ts_type), 6);
auto ts_nano_type = arrow::timestamp(arrow::TimeUnit::type::NANO);
ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_nano_type);
ASSERT_EQ(DateTimeUtils::GetPrecisionFromType(ts_type), 9);
}
TEST(DateTimeUtilsTest, TestGetTimeTypeFromArrowType) {
auto ts_sec_type = arrow::timestamp(arrow::TimeUnit::type::SECOND);
auto ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_sec_type);
ASSERT_EQ(DateTimeUtils::GetTimeTypeFromArrowType(ts_type), DateTimeUtils::TimeType::SECOND);
auto ts_milli_type = arrow::timestamp(arrow::TimeUnit::type::MILLI);
ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_milli_type);
ASSERT_EQ(DateTimeUtils::GetTimeTypeFromArrowType(ts_type),
DateTimeUtils::TimeType::MILLISECOND);
auto ts_micro_type = arrow::timestamp(arrow::TimeUnit::type::MICRO);
ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_micro_type);
ASSERT_EQ(DateTimeUtils::GetTimeTypeFromArrowType(ts_type),
DateTimeUtils::TimeType::MICROSECOND);
auto ts_nano_type = arrow::timestamp(arrow::TimeUnit::type::NANO);
ts_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(ts_nano_type);
ASSERT_EQ(DateTimeUtils::GetTimeTypeFromArrowType(ts_type),
DateTimeUtils::TimeType::NANOSECOND);
}
TEST(DateTimeUtilsTest, TestGetTypeFromPrecision) {
auto timezone = DateTimeUtils::GetLocalTimezoneName();
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(0, /*with_timezone=*/false));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::SECOND)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(0, /*with_timezone=*/true));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::SECOND, timezone)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(3, /*with_timezone=*/false));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::MILLI)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(3, /*with_timezone=*/true));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::MILLI, timezone)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(6, /*with_timezone=*/false));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::MICRO)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(6, /*with_timezone=*/true));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::MICRO, timezone)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(9, /*with_timezone=*/false));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::NANO)));
}
{
ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::DataType> ts_type,
DateTimeUtils::GetTypeFromPrecision(9, /*with_timezone=*/true));
ASSERT_TRUE(ts_type->Equals(arrow::timestamp(arrow::TimeUnit::type::NANO, timezone)));
}
{
ASSERT_NOK_WITH_MSG(DateTimeUtils::GetTypeFromPrecision(4, /*with_timezone=*/true),
"only support precision 0/3/6/9 in timestamp type");
}
}
TEST(DateTimeUtilsTest, TestGetLocalTimezoneName) {
std::string timezone = DateTimeUtils::GetLocalTimezoneName();
{
TimezoneGuard guard("US/Hawaii");
ASSERT_EQ(DateTimeUtils::GetLocalTimezoneName(), "US/Hawaii");
}
ASSERT_EQ(DateTimeUtils::GetLocalTimezoneName(), timezone);
}
TEST(DateTimeUtilsTest, TestGetCurrentLocalTimeUs) {
TimezoneGuard guard("Asia/Shanghai");
uint64_t utc_ts = DateTimeUtils::GetCurrentUTCTimeUs();
uint64_t local_ts = DateTimeUtils::GetCurrentLocalTimeUs().value();
ASSERT_GT(local_ts, utc_ts);
ASSERT_GE(local_ts - utc_ts, 28800000000l);
}
TEST(DateTimeUtilsTest, TestToLocalTimestamp) {
{
TimezoneGuard guard("Asia/Shanghai");
ASSERT_OK_AND_ASSIGN(Timestamp timestamp, DateTimeUtils::ToLocalTimestamp(
Timestamp::FromEpochMillis(1700000000123L)));
ASSERT_EQ(timestamp, Timestamp::FromEpochMillis(1700028800123L));
}
{
TimezoneGuard guard("UTC");
ASSERT_OK_AND_ASSIGN(Timestamp timestamp, DateTimeUtils::ToLocalTimestamp(
Timestamp::FromEpochMillis(1700000000123L)));
ASSERT_EQ(timestamp, Timestamp::FromEpochMillis(1700000000123L));
}
}
TEST(DateTimeUtilsTest, TestGetCurrentLocalHour) {
int32_t shanghai_hour = 0;
int32_t utc_hour = 0;
{
TimezoneGuard guard("Asia/Shanghai");
ASSERT_OK_AND_ASSIGN(shanghai_hour, DateTimeUtils::GetCurrentLocalHour());
}
{
TimezoneGuard guard("UTC");
ASSERT_OK_AND_ASSIGN(utc_hour, DateTimeUtils::GetCurrentLocalHour());
}
ASSERT_EQ((shanghai_hour - utc_hour + 24) % 24, 8);
}
TEST(DateTimeUtilsTest, TestToUTCTimestamp) {
TimezoneGuard guard("Asia/Shanghai");
{
Timestamp ts(0, 0);
ASSERT_OK_AND_ASSIGN(Timestamp utc_ts, DateTimeUtils::ToUTCTimestamp(ts));
ASSERT_EQ(utc_ts, Timestamp(-28800000l, 0));
}
{
// test precision loss for nano
Timestamp ts(0, 500);
ASSERT_OK_AND_ASSIGN(Timestamp utc_ts, DateTimeUtils::ToUTCTimestamp(ts));
ASSERT_EQ(utc_ts, Timestamp(-28800000l, 0));
}
}
TEST(DateTimeUtilsTest, TestGetArrowTimeUnitStr) {
ASSERT_EQ(DateTimeUtils::GetArrowTimeUnitStr(arrow::TimeUnit::SECOND), "SECOND");
ASSERT_EQ(DateTimeUtils::GetArrowTimeUnitStr(arrow::TimeUnit::MILLI), "MILLISECOND");
ASSERT_EQ(DateTimeUtils::GetArrowTimeUnitStr(arrow::TimeUnit::MICRO), "MICROSECOND");
ASSERT_EQ(DateTimeUtils::GetArrowTimeUnitStr(arrow::TimeUnit::NANO), "NANOSECOND");
}
} // namespace paimon::test