This is an automated email from the ASF dual-hosted git repository.

morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new 1d8f09a369f branch-3.1: [fix](timezone) Fix incorrect DST handling 
#51454 (#52420)
1d8f09a369f is described below

commit 1d8f09a369f4a254859dd326a8c2a839b12d04a6
Author: zclllyybb <[email protected]>
AuthorDate: Sat Jun 28 22:52:30 2025 +0800

    branch-3.1: [fix](timezone) Fix incorrect DST handling #51454 (#52420)
    
    Cherry-pick from #51454
---
 be/src/vec/runtime/vdatetime_value.cpp             |  57 +++++++++------------
 be/src/vec/runtime/vdatetime_value.h               |  20 ++++----
 .../data/datatype_p0/datetimev2/test_timezone.out  | Bin 628 -> 434 bytes
 .../datatype_p0/datetimev2/test_tz_streamload.out  | Bin 627 -> 627 bytes
 .../datatype_p0/datetimev2/test_timezone.groovy    |   5 ++
 5 files changed, 38 insertions(+), 44 deletions(-)

diff --git a/be/src/vec/runtime/vdatetime_value.cpp 
b/be/src/vec/runtime/vdatetime_value.cpp
index d161c64fd1f..ef6aa7e95eb 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -2041,7 +2041,7 @@ bool DateV2Value<T>::from_date_str_base(const char* 
date_str, int len, int scale
 
     int field_idx = 0;
     int field_len = year_len;
-    long sec_offset = 0;
+    int sec_offset = 0;
     bool need_use_timezone = false;
 
     while (ptr < end && isdigit(*ptr) && field_idx < MAX_DATE_PARTS) {
@@ -2206,40 +2206,29 @@ bool DateV2Value<T>::from_date_str_base(const char* 
date_str, int len, int scale
         if (!TimezoneUtils::find_cctz_time_zone(std::string {ptr, end}, 
given_tz)) {
             return false; // invalid format
         }
-        auto given = cctz::convert(cctz::civil_second {}, given_tz);
-        auto local = cctz::convert(cctz::civil_second {}, *local_time_zone);
-        // these two values is absolute time. so they are negative. need to 
use (-local) - (-given)
-        sec_offset = std::chrono::duration_cast<std::chrono::seconds>(given - 
local).count();
-    }
-
-    // In check_range_and_set_time, for Date type the time part will be 
truncated. So if the timezone offset should make
-    // rounding to date part, it would be lost. To avoid this, we use a 
Datetime type to do these calc. It will save the
-    // time part and apply the offset. Then convert to Date type back.
-    // see https://github.com/apache/doris/pull/33553 for more details.
-    if constexpr (!is_datetime) {
-        if (sec_offset) {
-            DateV2Value<DateTimeV2ValueType> tmp;
-            if (!tmp.check_range_and_set_time(date_val[0], date_val[1], 
date_val[2], date_val[3],
-                                              date_val[4], date_val[5], 
date_val[6])) {
-                return false;
-            }
-            if (!tmp.date_add_interval<TimeUnit::SECOND>(
-                        TimeInterval {TimeUnit::SECOND, sec_offset, false})) {
-                return false;
-            }
-            this->assign_from(tmp);
-            return true;
+        if (is_invalid(date_val[0], date_val[1], date_val[2], date_val[3], 
date_val[4], date_val[5],
+                       date_val[6])) {
+            return false;
         }
-    }
-
-    if (!check_range_and_set_time(date_val[0], date_val[1], date_val[2], 
date_val[3], date_val[4],
-                                  date_val[5], date_val[6])) {
-        return false;
-    }
-
-    return sec_offset ? date_add_interval<TimeUnit::SECOND>(
-                                TimeInterval {TimeUnit::SECOND, sec_offset, 
false})
-                      : true;
+        // will carring on the bits in cctz::civil_second. if day is 70, will 
carry to month.
+        cctz::civil_second cs {date_val[0], date_val[1], date_val[2],
+                               date_val[3], date_val[4], date_val[5]};
+
+        auto given = cctz::convert(cs, given_tz);
+        auto local = cctz::convert(given, *local_time_zone);
+        date_val[0] = local.year();
+        date_val[1] = local.month();
+        date_val[2] = local.day();
+        date_val[3] = local.hour();
+        date_val[4] = local.minute();
+        date_val[5] = local.second();
+    }
+
+    return check_range_and_set_time(date_val[0], date_val[1], date_val[2], 
date_val[3], date_val[4],
+                                    date_val[5], date_val[6]) &&
+           (sec_offset ? date_add_interval<TimeUnit::SECOND>(
+                                 TimeInterval {TimeUnit::SECOND, sec_offset, 
false})
+                       : true);
 }
 
 template <typename T>
diff --git a/be/src/vec/runtime/vdatetime_value.h 
b/be/src/vec/runtime/vdatetime_value.h
index b337fea46a2..12e961f5fa9 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -1024,8 +1024,8 @@ public:
     }
 
     bool operator==(const VecDateTimeValue& other) const {
-        int64_t ts1;
-        int64_t ts2;
+        int64_t ts1 = 0;
+        int64_t ts2 = 0;
         this->unix_timestamp(&ts1, TimezoneUtils::default_time_zone);
         other.unix_timestamp(&ts2, TimezoneUtils::default_time_zone);
         return ts1 == ts2;
@@ -1040,8 +1040,8 @@ public:
     bool operator<=(const DateV2Value<T>& other) const { return !(*this > 
other); }
 
     bool operator<=(const VecDateTimeValue& other) const {
-        int64_t ts1;
-        int64_t ts2;
+        int64_t ts1 = 0;
+        int64_t ts2 = 0;
         this->unix_timestamp(&ts1, TimezoneUtils::default_time_zone);
         other.unix_timestamp(&ts2, TimezoneUtils::default_time_zone);
         return ts1 <= ts2;
@@ -1050,8 +1050,8 @@ public:
     bool operator>=(const DateV2Value<T>& other) const { return !(*this < 
other); }
 
     bool operator>=(const VecDateTimeValue& other) const {
-        int64_t ts1;
-        int64_t ts2;
+        int64_t ts1 = 0;
+        int64_t ts2 = 0;
         this->unix_timestamp(&ts1, TimezoneUtils::default_time_zone);
         other.unix_timestamp(&ts2, TimezoneUtils::default_time_zone);
         return ts1 >= ts2;
@@ -1062,8 +1062,8 @@ public:
     }
 
     bool operator<(const VecDateTimeValue& other) const {
-        int64_t ts1;
-        int64_t ts2;
+        int64_t ts1 = 0;
+        int64_t ts2 = 0;
         this->unix_timestamp(&ts1, TimezoneUtils::default_time_zone);
         other.unix_timestamp(&ts2, TimezoneUtils::default_time_zone);
         return ts1 < ts2;
@@ -1074,8 +1074,8 @@ public:
     }
 
     bool operator>(const VecDateTimeValue& other) const {
-        int64_t ts1;
-        int64_t ts2;
+        int64_t ts1 = 0;
+        int64_t ts2 = 0;
         this->unix_timestamp(&ts1, TimezoneUtils::default_time_zone);
         other.unix_timestamp(&ts2, TimezoneUtils::default_time_zone);
         return ts1 > ts2;
diff --git a/regression-test/data/datatype_p0/datetimev2/test_timezone.out 
b/regression-test/data/datatype_p0/datetimev2/test_timezone.out
index 1fae14def39..6b1b3ebb41d 100644
Binary files a/regression-test/data/datatype_p0/datetimev2/test_timezone.out 
and b/regression-test/data/datatype_p0/datetimev2/test_timezone.out differ
diff --git a/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out 
b/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out
index ab103c3a306..a05ac54d305 100644
Binary files 
a/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out and 
b/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out differ
diff --git a/regression-test/suites/datatype_p0/datetimev2/test_timezone.groovy 
b/regression-test/suites/datatype_p0/datetimev2/test_timezone.groovy
index 746a78de441..5d3d7c272ca 100644
--- a/regression-test/suites/datatype_p0/datetimev2/test_timezone.groovy
+++ b/regression-test/suites/datatype_p0/datetimev2/test_timezone.groovy
@@ -43,4 +43,9 @@ suite("test_timezone") {
     qt_fold1 """ select cast('2020-12-12T12:12:12asia/shanghai' as datetime); 
"""
     qt_fold2 """ select cast('2020-12-12T12:12:12america/los_angeLES' as 
datetime); """
     qt_fold3 """ select cast('2020-12-12T12:12:12Europe/pARIS' as datetime); 
"""
+
+    qt_nodst "select cast('2010-01-05 08:15:30Europe/London' as datetime);"
+    qt_dst "select cast('2010-08-05 08:15:30Europe/London' as datetime);"
+    testFoldConst ("select cast('2010-01-05 08:15:30Europe/London' as 
datetime);")
+    testFoldConst ("select cast('2010-08-05 08:15:30Europe/London' as 
datetime);")
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to