diff --git a/src/IO/ReadHelpers.h b/src/IO/ReadHelpers.h index feacbd085c2..664c4daf8e2 100644 --- a/src/IO/ReadHelpers.h +++ b/src/IO/ReadHelpers.h @@ -908,6 +908,8 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re return ReturnType(false); } + int negative_multiplier = 1; + DB::DecimalUtils::DecimalComponents components{static_cast(whole), 0}; if (!buf.eof() && *buf.position() == '.') @@ -934,29 +936,17 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re while (!buf.eof() && isNumericASCII(*buf.position())) ++buf.position(); - /// Keep sign of fractional part the same with whole part if datetime64 is negative - /// Case1: - /// 1965-12-12 12:12:12.123 - /// => whole = -127914468, fractional = 123(coefficient>0) - /// => new whole = -127914467, new fractional = 877(coefficient<0) - /// - /// Case2: - /// 1969-12-31 23:59:59.123 - /// => whole = -1, fractional = 123(coefficient>0) - /// => new whole = 0, new fractional = -877(coefficient>0) + /// Fractional part (subseconds) is treated as positive by users + /// (as DateTime64 itself is a positive, although underlying decimal is negative), + /// so it needs proper handling if (components.whole < 0 && components.fractional != 0) { const auto scale_multiplier = DecimalUtils::scaleMultiplier(scale); ++components.whole; - if (components.whole) + components.fractional = scale_multiplier - components.fractional; + if (!components.whole) { - /// whole keep the sign, fractional should be non-negative - components.fractional = scale_multiplier - components.fractional; - } - else - { - /// when whole is zero, fractional should keep the sign - components.fractional = components.fractional - scale_multiplier; + negative_multiplier = -1; } } } @@ -969,7 +959,7 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re components.whole = components.whole / common::exp10_i32(scale); } - datetime64 = DecimalUtils::decimalFromComponents(components, scale); + datetime64 = negative_multiplier * DecimalUtils::decimalFromComponents(components, scale); return ReturnType(true); }