Fix millisecond calculation

This commit is contained in:
Blargian 2024-02-29 18:05:49 +01:00
parent b380d06e6e
commit f1c9b1abcd
4 changed files with 35 additions and 23 deletions

View File

@ -3,6 +3,7 @@
#include <base/DayNum.h>
#include <base/defines.h>
#include <base/types.h>
#include <Core/DecimalFunctions.h>
#include <ctime>
#include <cassert>
@ -216,7 +217,6 @@ private:
Time offset_at_start_of_lut;
bool offset_is_whole_number_of_hours_during_epoch;
bool offset_is_whole_number_of_minutes_during_epoch;
bool offset_is_whole_number_of_seconds_during_epoch;
/// Time zone name.
std::string time_zone;
@ -593,17 +593,28 @@ public:
return time % 60;
}
unsigned toMillisecond(Time t) const
template <typename DateOrTime>
unsigned toMillisecond(const DateOrTime & datetime, Int64 scale_multiplier) const
{
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
return (t % 60) * 1000;
const auto microsecond_multiplier = 1000000;
const auto millisecond_multiplier = 1000;
LUTIndex index = findIndex(t);
Time time = t - lut[index].date;
auto components = DB::DecimalUtils::splitWithScaleMultiplier(datetime, scale_multiplier);
if (time >= lut[index].time_at_offset_change())
time += lut[index].amount_of_offset_change();
return (time % 60) * 1000;
if (datetime.value < 0 && components.fractional)
{
components.fractional = scale_multiplier + (components.whole ? Int64(-1) : Int64(1)) * components.fractional;
--components.whole;
}
Int64 fractional = components.fractional;
if (scale_multiplier > microsecond_multiplier)
fractional = fractional / (scale_multiplier / microsecond_multiplier);
else if (scale_multiplier < microsecond_multiplier)
fractional = fractional * (microsecond_multiplier / scale_multiplier);
constexpr Int64 divider = microsecond_multiplier / millisecond_multiplier;
UInt16 millisecond = static_cast<UInt16>(fractional / divider);
return millisecond;
}
unsigned toMinute(Time t) const

View File

@ -6,6 +6,7 @@
#include <Common/DateLUTImpl.h>
#include <Common/DateLUT.h>
#include <Common/IntervalKind.h>
#include "base/Decimal.h"
#include <Columns/ColumnNullable.h>
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnVector.h>
@ -1522,13 +1523,14 @@ struct ToMillisecondImpl
{
static constexpr auto name = "toMillisecond";
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
static UInt16 execute(const DateTime64 & datetime64, Int64 scale_multiplier, const DateLUTImpl & time_zone)
{
return time_zone.toMillisecond(t);
return time_zone.toMillisecond<DateTime64>(datetime64, scale_multiplier);
}
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
static UInt16 execute(UInt32, const DateLUTImpl &)
{
return time_zone.toMillisecond(t);
return 0; /// Only DateTime64 type will give a value for milliseconds
}
static UInt16 execute(Int32, const DateLUTImpl &)
{
@ -1540,7 +1542,7 @@ struct ToMillisecondImpl
}
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfSecondImpl;
using FactorTransform = ZeroTransform;
};
struct ToISOYearImpl

View File

@ -1,8 +1,6 @@
#include <Functions/FunctionFactory.h>
#include <Functions/DateTimeTransforms.h>
#include <Functions/FunctionDateOrDateTimeToSomething.h>
#include <DataTypes/DataTypesNumber.h>
namespace DB
{

View File

@ -1,7 +1,8 @@
2023-04-21 10:20:30 30000 30000
2023-04-21 10:20:30 30000 30000
2023-04-21 10:20:30.123 30000 30000
2023-04-21 10:20:30.123456 30000 30000
30000
2023-04-21 10:20:30 30000
2023-04-21 10:20:30 30000
2023-04-21 10:20:30 0 0
2023-04-21 10:20:30 0 0
2023-04-21 10:20:30.123 123 123
2023-04-21 10:20:30.123456 123 123
2023-04-21 10:20:30.123456789 123 123
120
2023-04-21 10:20:30 0
2023-04-21 10:20:30 0