mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Fix wrong result of datetime64 when negative (#35440)
This commit is contained in:
parent
d77678d1d1
commit
a1e54c3918
@ -117,6 +117,31 @@ TEST_P(DecimalUtilsSplitAndCombineTest, getFractionalPartDecimal128)
|
||||
testGetFractional<Decimal128>(GetParam());
|
||||
}
|
||||
|
||||
class DecimalUtilsSplitAndCombineForDateTime64Test : public ::testing::TestWithParam<DecimalUtilsSplitAndCombineTestParam>
|
||||
{};
|
||||
|
||||
|
||||
// Unfortunately typed parametrized tests () are not supported in this version of gtest, so I have to emulate by hand.
|
||||
TEST_P(DecimalUtilsSplitAndCombineForDateTime64Test, splitDateTime64)
|
||||
{
|
||||
testSplit<DateTime64>(GetParam());
|
||||
}
|
||||
|
||||
TEST_P(DecimalUtilsSplitAndCombineForDateTime64Test, combineDateTime64)
|
||||
{
|
||||
testDecimalFromComponents<DateTime64>(GetParam());
|
||||
}
|
||||
|
||||
TEST_P(DecimalUtilsSplitAndCombineForDateTime64Test, getWholePartDateTime64)
|
||||
{
|
||||
testGetWhole<DateTime64>(GetParam());
|
||||
}
|
||||
|
||||
TEST_P(DecimalUtilsSplitAndCombineForDateTime64Test, getFractionalPartDateTime64)
|
||||
{
|
||||
testGetFractional<DateTime64>(GetParam());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Intentionally small values that fit into 32-bit in order to cover Decimal32, Decimal64 and Decimal128 with single set of data.
|
||||
@ -170,3 +195,27 @@ INSTANTIATE_TEST_SUITE_P(Basic,
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(Basic,
|
||||
DecimalUtilsSplitAndCombineForDateTime64Test,
|
||||
::testing::ValuesIn(std::initializer_list<DecimalUtilsSplitAndCombineTestParam>{
|
||||
{
|
||||
"Negative timestamp 1965-12-12 12:12:12.123 UTC",
|
||||
DateTime64(-127943267877),
|
||||
3,
|
||||
{
|
||||
-127943267,
|
||||
877
|
||||
}
|
||||
},
|
||||
{
|
||||
"Positive timestamp 1975-12-12 12:12:12.123 UTC",
|
||||
DateTime64(187618332123),
|
||||
3,
|
||||
{
|
||||
187618332,
|
||||
123
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -929,6 +929,15 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
|
||||
/// Ignore digits that are out of precision.
|
||||
while (!buf.eof() && isNumericASCII(*buf.position()))
|
||||
++buf.position();
|
||||
|
||||
/// Keep sign of fractional part the same with whole part if datetime64 is negative
|
||||
/// 1965-12-12 12:12:12.123 => whole = -127914468, fraction = 123(sign>0) -> new whole = -127914467, new fraction = 877(sign<0)
|
||||
if (components.whole < 0 && components.fractional != 0)
|
||||
{
|
||||
const auto scale_multiplier = DecimalUtils::scaleMultiplier<DateTime64::NativeType>(scale);
|
||||
++components.whole;
|
||||
components.fractional = scale_multiplier - components.fractional;
|
||||
}
|
||||
}
|
||||
/// 9908870400 is time_t value for 2184-01-01 UTC (a bit over the last year supported by DateTime64)
|
||||
else if (whole >= 9908870400LL)
|
||||
|
@ -805,6 +805,13 @@ inline void writeDateTimeText(DateTime64 datetime64, UInt32 scale, WriteBuffer &
|
||||
scale = scale > MaxScale ? MaxScale : scale;
|
||||
|
||||
auto components = DecimalUtils::split(datetime64, scale);
|
||||
/// -127914467.877 => whole = -127914467, fraction = 877 => new whole = -127914468(1965-12-12 12:12:12), new fraction = 123(.123) => 1965-12-12 12:12:12.123
|
||||
if (components.whole < 0 && components.fractional != 0)
|
||||
{
|
||||
--components.whole;
|
||||
components.fractional = DecimalUtils::scaleMultiplier<DateTime64::NativeType>(scale) - components.fractional;
|
||||
}
|
||||
|
||||
writeDateTimeText<date_delimeter, time_delimeter, between_date_time_delimiter>(LocalDateTime(components.whole, time_zone), buf);
|
||||
|
||||
if (scale > 0)
|
||||
|
@ -4,6 +4,6 @@ Asia/Makassar 1234567891011 2009-02-14 07:31:31.011 1970-01-15 14:56:07.891011 1
|
||||
non-const column
|
||||
1234567891011 2009-02-13 23:31:31.011 1970-01-15 06:56:07.891011 1970-01-01 00:20:34.567891011
|
||||
upper range bound
|
||||
9904447342 2283-11-10 19:22:22.123 2283-11-10 19:22:22.123456 1925-01-01 00:00:00.586094827
|
||||
9904447342 2283-11-10 19:22:22.123 2283-11-10 19:22:22.123456 1925-01-01 00:00:00.413905173
|
||||
lower range bound
|
||||
-1420066799 1925-01-01 01:00:01.123 1925-01-01 01:00:01.123456 1925-01-01 01:00:01.123456789
|
||||
-1420066799 1925-01-01 01:00:00.877 1925-01-01 01:00:00.876544 1925-01-01 01:00:00.876543211
|
||||
|
@ -1,4 +1,4 @@
|
||||
1940-10-09 22:13:17.6
|
||||
2283-11-11 23:46:43.6
|
||||
2283-11-11 23:46:40.1
|
||||
1925-01-01 00:00:00.1
|
||||
1925-01-01 00:00:00.9
|
||||
|
@ -14,7 +14,7 @@ test intervals
|
||||
1980-12-12 12:12:12.123456
|
||||
1930-12-12 12:12:12.123456
|
||||
1930-12-12 12:12:12.123400
|
||||
1930-12-12 12:12:12.123457
|
||||
1930-12-12 12:12:12.123456
|
||||
2220-12-12 12:12:12.123456
|
||||
2220-12-12 12:12:12.123400
|
||||
2220-12-12 12:12:12.123456
|
||||
@ -25,7 +25,7 @@ test intervals
|
||||
1980-12-12 12:12:12.123
|
||||
1930-12-12 12:12:12.123
|
||||
1930-12-12 12:12:12.120
|
||||
1930-12-12 12:12:12.124
|
||||
1930-12-12 12:12:12.123
|
||||
2220-12-12 12:12:12.123
|
||||
2220-12-12 12:12:12.120
|
||||
2220-12-12 12:12:12.123
|
||||
@ -34,8 +34,8 @@ test add[...]seconds()
|
||||
1980-12-12 12:12:12.123456790
|
||||
1980-12-12 12:12:12.123456701
|
||||
1980-12-12 12:12:12.123456790
|
||||
1930-12-12 12:12:12.123456788
|
||||
1930-12-12 12:12:12.123456699
|
||||
1930-12-12 12:12:12.123456790
|
||||
1930-12-12 12:12:12.123456701
|
||||
2220-12-12 12:12:12.123456790
|
||||
2220-12-12 12:12:12.123456701
|
||||
- test microseconds
|
||||
@ -43,9 +43,9 @@ test add[...]seconds()
|
||||
1980-12-12 12:12:12.123401
|
||||
1980-12-12 12:12:12.12345778
|
||||
1980-12-12 12:12:12.123457
|
||||
1930-12-12 12:12:12.123455
|
||||
1930-12-12 12:12:12.123399
|
||||
1930-12-12 12:12:12.12345578
|
||||
1930-12-12 12:12:12.123457
|
||||
1930-12-12 12:12:12.123401
|
||||
1930-12-12 12:12:12.12345778
|
||||
2220-12-12 12:12:12.123457
|
||||
2220-12-12 12:12:12.123401
|
||||
2220-12-12 12:12:12.12345778
|
||||
@ -54,9 +54,9 @@ test add[...]seconds()
|
||||
1980-12-12 12:12:12.121
|
||||
1980-12-12 12:12:12.124456
|
||||
1980-12-12 12:12:12.124
|
||||
1930-12-12 12:12:12.122
|
||||
1930-12-12 12:12:12.119
|
||||
1930-12-12 12:12:12.122456
|
||||
1930-12-12 12:12:12.124
|
||||
1930-12-12 12:12:12.121
|
||||
1930-12-12 12:12:12.124456
|
||||
2220-12-12 12:12:12.124
|
||||
2220-12-12 12:12:12.121
|
||||
2220-12-12 12:12:12.124456
|
||||
|
@ -0,0 +1,2 @@
|
||||
-127914467.877
|
||||
187618332.123
|
2
tests/queries/0_stateless/02242_negative_datetime64.sql
Normal file
2
tests/queries/0_stateless/02242_negative_datetime64.sql
Normal file
@ -0,0 +1,2 @@
|
||||
SELECT cast(toDateTime64('1965-12-12 12:12:12.123', 3, 'UTC') as Decimal64(3));
|
||||
SELECT cast(toDateTime64('1975-12-12 12:12:12.123', 3, 'UTC') as Decimal64(3));
|
Loading…
Reference in New Issue
Block a user