hanyuzheng7 commented on code in PR #25897:
URL: https://github.com/apache/flink/pull/25897#discussion_r1948364110


##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1290,6 +1353,24 @@ private static long floor(long a, long b) {
         }
     }
 
+    private static long floor(long a, int b) {

Review Comment:
   I use a and b just follow other exist method, yes, I think I can rename a 
and b and let them more meaning for.
   q stand for quotient and r stand for remainder.



##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1299,6 +1380,39 @@ private static long ceil(long a, long b) {
         }
     }
 
+    private static long ceil(long a, int b) {
+        float q = (float) b / NANOS_PER_MILLISECOND;
+        if (q > 0) {
+            return a + 1L;
+        } else {
+            return a;
+        }
+    }
+
+    private static int ceilForHighPrecision(int b) {

Review Comment:
   Ok, I will rename it.



##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1290,6 +1353,24 @@ private static long floor(long a, long b) {
         }
     }
 
+    private static long floor(long a, int b) {
+        long q = b / NANOS_PER_MILLISECOND;
+        if (q < 0) {
+            return a - q;
+        } else {
+            return a;
+        }
+    }

Review Comment:
   Not cover any test, Yes, I think we need check if a is negative, if a < 0 we 
need return a + q, otherwise return a, because we need handle the case when 
utcTs < 0, because in this case, it stand for the time 
   before 1970.
   The logic should be
   ```
   return a > 0 ? a  : a + q
   ```



##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1299,6 +1380,39 @@ private static long ceil(long a, long b) {
         }
     }
 
+    private static long ceil(long a, int b) {
+        float q = (float) b / NANOS_PER_MILLISECOND;
+        if (q > 0) {
+            return a + 1L;
+        } else {
+            return a;
+        }
+    }
+
+    private static int ceilForHighPrecision(int b) {
+        long q = b / NANOS_PER_MICROSECOND;

Review Comment:
   Actually except a and b, other parameters has its' meaning.
   The reason I use a and b is other floor and ceil functions use a and b, so I 
followed them. eg: 
https://github.com/apache/flink/pull/25897/files#diff-e29751e95291efb2d7e399b60ee820322a29d24a716b7373a121a5d4d617aefbR1374
   
   q stand for quotient and  r stand for remainder.
   



##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/codegen/calls/BuiltInMethods.scala:
##########
@@ -386,15 +386,29 @@ object BuiltInMethods {
     "timestampFloor",
     classOf[TimeUnitRange],
     classOf[Long],
+    classOf[Int],
     classOf[TimeZone])
 
+  val TIMESTAMP_FLOOR_TIME_ZONE_FOR_HIGH_PRECISiON = Types.lookupMethod(

Review Comment:
   Will update the name.



##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1299,6 +1380,39 @@ private static long ceil(long a, long b) {
         }
     }
 
+    private static long ceil(long a, int b) {
+        float q = (float) b / NANOS_PER_MILLISECOND;

Review Comment:
   The logic should like this
   ```
    return a > 0 ? a + 1L : a
   ```
   
   



##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/TimeFunctionsITCase.java:
##########
@@ -50,7 +50,7 @@
 class TimeFunctionsITCase extends BuiltInFunctionTestBase {
 
     private static final DateTimeFormatter TIMESTAMP_FORMATTER =
-            DateTimeFormatter.ofPattern("yyyy-MM-dd' 'HH:mm:ss.SSS");
+            DateTimeFormatter.ofPattern("yyyy-MM-dd' 'HH:mm:ss.SSSSSSSSS");

Review Comment:
   No, because we test nano second and microsecond at this time,  we have to 
increase the precision, otherwise we cannot test whether last 6 digits is 
correct or not.



##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1290,6 +1353,24 @@ private static long floor(long a, long b) {
         }
     }
 
+    private static long floor(long a, int b) {
+        long q = b / NANOS_PER_MILLISECOND;
+        if (q < 0) {
+            return a - q;
+        } else {
+            return a;
+        }
+    }
+
+    private static int floorForHighPrecision(int b) {
+        long q = b / NANOS_PER_MICROSECOND;

Review Comment:
   We don't need check if q < 0 or not, we need check if utcTs < 0 here.
   So the logic should like this
   ```
   return (a < 0 ? q -1 : q) * NANOS_PER_MICROSECOND;
   ```



##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java:
##########
@@ -1275,7 +1314,31 @@ public static long timestampCeil(TimeUnitRange range, 
long ts, TimeZone tz) {
                 int days = (int) (utcTs / MILLIS_PER_DAY + EPOCH_JULIAN);
                 return julianDateFloor(range, days, false) * MILLIS_PER_DAY - 
offset;
             default:
-                // for MINUTE and SECONDS etc...,
+                // it is more effective to use arithmetic Method
+                throw new AssertionError(range);
+        }
+    }
+
+    public static int timestampCeilForHighPrecision(TimeUnitRange range, int 
ns) {
+        switch (range) {
+            case NANOSECOND:
+                return ns;
+            case MICROSECOND:
+                return ceilForHighPrecision(ns);
+            case MILLISECOND:

Review Comment:
   if we can handle below specific case, we can optimize the logic for these 
two methods, but we cannot remove them, because these two method return 
nanosecond. We cannot use one method, because of the structure for 
FloorCeilCallGen.scala, we have to deliver two methods together.
   
   The specific case is here:
   `TimestampData` has a restriction
   ```
       private TimestampData(long millisecond, int nanoOfMillisecond) {
           Preconditions.checkArgument(nanoOfMillisecond >= 0 && 
nanoOfMillisecond <= 999_999);
           this.millisecond = millisecond;
           this.nanoOfMillisecond = nanoOfMillisecond;
       }
   ```
   The `nanoOfMillisecond <= 999_999`, if we change it to `nanoOfMillisecond <= 
1_000_000`, when we meet `999_999 + 1` this situation, it will not throw 
exception. So we don't  have to need a logic to check this specific situation.
   
   Now when this situation happen, `999_999 + 1 = 1_000_000`
   ceilForHighPrecision will return 0, and ceilForHighPrecision will add 1 to 
handle this specific case.
   ```
      private static int ceilForHighPrecision(int b) {
           long q = b / NANOS_PER_MICROSECOND;
           long r = b % NANOS_PER_MICROSECOND;
           if (q > 0 && r > 0) {
               if (q + 1 == NANOS_PER_MICROSECOND) {
                   return 0;
               }
               return (int) ((q + 1) * NANOS_PER_MICROSECOND);
           } else {
               return (int) (q * NANOS_PER_MICROSECOND);
           }
       }
   ```
   
   ```
   private static long ceilForHighPrecision(long a, int b) {
           long q = b / NANOS_PER_MICROSECOND;
           long r = b % NANOS_PER_MICROSECOND;
           if (q > 0 && r > 0) {
               if (q + 1 == NANOS_PER_MICROSECOND) {
                   return a + 1L;
               }
           }
           return a;
       }
   
   ```
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to