DateTimeUtils.java

1
/*
2
 * Copyright OpenSearch Contributors
3
 * SPDX-License-Identifier: Apache-2.0
4
 */
5
6
package org.opensearch.sql.utils;
7
8
import java.time.Instant;
9
import java.time.LocalDateTime;
10
import java.time.ZoneId;
11
import java.time.ZonedDateTime;
12
import lombok.experimental.UtilityClass;
13
14
@UtilityClass
15
public class DateTimeUtils {
16
17
  /**
18
   * Util method to round the date/time with given unit.
19
   *
20
   * @param utcMillis     Date/time value to round, given in utc millis
21
   * @param unitMillis    Date/time interval unit in utc millis
22
   * @return              Rounded date/time value in utc millis
23
   */
24
  public static long roundFloor(long utcMillis, long unitMillis) {
25 3 1. roundFloor : Replaced long modulus with multiplication → KILLED
2. roundFloor : Replaced long subtraction with addition → KILLED
3. roundFloor : replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundFloor → KILLED
    return utcMillis - utcMillis % unitMillis;
26
  }
27
28
  /**
29
   * Util method to round the date/time in week(s).
30
   *
31
   * @param utcMillis     Date/time value to round, given in utc millis
32
   * @param interval      Number of weeks as the rounding interval
33
   * @return              Rounded date/time value in utc millis
34
   */
35
  public static long roundWeek(long utcMillis, int interval) {
36 4 1. roundWeek : Replaced long addition with subtraction → SURVIVED
2. roundWeek : Replaced long multiplication with division → KILLED
3. roundWeek : Replaced long subtraction with addition → KILLED
4. roundWeek : replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundWeek → KILLED
    return roundFloor(utcMillis + 259200000L, 604800000L * interval) - 259200000L;
37
  }
38
39
  /**
40
   * Util method to round the date/time in month(s).
41
   *
42
   * @param utcMillis     Date/time value to round, given in utc millis
43
   * @param interval      Number of months as the rounding interval
44
   * @return              Rounded date/time value in utc millis
45
   */
46
  public static long roundMonth(long utcMillis, int interval) {
47
    ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
48
    ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(ZoneId.of("UTC"))
49
        .plusMonths(interval);
50 2 1. roundMonth : Replaced integer subtraction with addition → KILLED
2. roundMonth : Replaced long multiplication with division → KILLED
    long monthDiff = (zonedDateTime.getYear() - initDateTime.getYear()) * 12L + zonedDateTime
51 2 1. roundMonth : Replaced long addition with subtraction → KILLED
2. roundMonth : Replaced long subtraction with addition → KILLED
        .getMonthValue() - initDateTime.getMonthValue();
52 3 1. roundMonth : Replaced long division with multiplication → KILLED
2. roundMonth : Replaced long subtraction with addition → KILLED
3. roundMonth : Replaced long multiplication with division → KILLED
    long monthToAdd = (monthDiff / interval - 1) * interval;
53 1 1. roundMonth : replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundMonth → KILLED
    return initDateTime.plusMonths(monthToAdd).toInstant().toEpochMilli();
54
  }
55
56
  /**
57
   * Util method to round the date/time in quarter(s).
58
   *
59
   * @param utcMillis     Date/time value to round, given in utc millis
60
   * @param interval      Number of quarters as the rounding interval
61
   * @return              Rounded date/time value in utc millis
62
   */
63
  public static long roundQuarter(long utcMillis, int interval) {
64
    ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
65 1 1. roundQuarter : Replaced long multiplication with division → KILLED
    ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(ZoneId.of("UTC"))
66
        .plusMonths(interval * 3L);
67 2 1. roundQuarter : Replaced integer subtraction with addition → KILLED
2. roundQuarter : Replaced long multiplication with division → KILLED
    long monthDiff = ((zonedDateTime.getYear() - initDateTime.getYear()) * 12L + zonedDateTime
68 2 1. roundQuarter : Replaced long addition with subtraction → KILLED
2. roundQuarter : Replaced long subtraction with addition → KILLED
        .getMonthValue() - initDateTime.getMonthValue());
69 5 1. roundQuarter : Replaced long multiplication with division → KILLED
2. roundQuarter : Replaced long division with multiplication → KILLED
3. roundQuarter : Replaced long subtraction with addition → KILLED
4. roundQuarter : Replaced long multiplication with division → KILLED
5. roundQuarter : Replaced long multiplication with division → KILLED
    long monthToAdd = (monthDiff / (interval * 3L) - 1) * interval * 3;
70 1 1. roundQuarter : replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundQuarter → KILLED
    return initDateTime.plusMonths(monthToAdd).toInstant().toEpochMilli();
71
  }
72
73
  /**
74
   * Util method to round the date/time in year(s).
75
   *
76
   * @param utcMillis     Date/time value to round, given in utc millis
77
   * @param interval      Number of years as the rounding interval
78
   * @return              Rounded date/time value in utc millis
79
   */
80
  public static long roundYear(long utcMillis, int interval) {
81
    ZonedDateTime initDateTime = ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
82
    ZonedDateTime zonedDateTime = Instant.ofEpochMilli(utcMillis).atZone(ZoneId.of("UTC"));
83 1 1. roundYear : Replaced integer subtraction with addition → KILLED
    int yearDiff = zonedDateTime.getYear() - initDateTime.getYear();
84 2 1. roundYear : Replaced integer division with multiplication → KILLED
2. roundYear : Replaced integer multiplication with division → KILLED
    int yearToAdd = (yearDiff / interval) * interval;
85 1 1. roundYear : replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundYear → KILLED
    return initDateTime.plusYears(yearToAdd).toInstant().toEpochMilli();
86
  }
87
88
89
  /**
90
   * isValidMySqlTimeZoneId for timezones which match timezone the range set by MySQL.
91
   *
92
   * @param zone ZoneId of ZoneId type.
93
   * @return Boolean.
94
   */
95
  public Boolean isValidMySqlTimeZoneId(ZoneId zone) {
96
    String timeZoneMax = "+14:00";
97
    String timeZoneMin = "-13:59";
98
    String timeZoneZero = "+00:00";
99
100
    ZoneId maxTz = ZoneId.of(timeZoneMax);
101
    ZoneId minTz = ZoneId.of(timeZoneMin);
102
    ZoneId defaultTz = ZoneId.of(timeZoneZero);
103
104
    ZonedDateTime defaultDateTime = LocalDateTime.of(2000, 1, 2, 12, 0).atZone(defaultTz);
105
106
    ZonedDateTime maxTzValidator =
107
        defaultDateTime.withZoneSameInstant(maxTz).withZoneSameLocal(defaultTz);
108
    ZonedDateTime minTzValidator =
109
        defaultDateTime.withZoneSameInstant(minTz).withZoneSameLocal(defaultTz);
110
    ZonedDateTime passedTzValidator =
111
        defaultDateTime.withZoneSameInstant(zone).withZoneSameLocal(defaultTz);
112
113 2 1. isValidMySqlTimeZoneId : negated conditional → KILLED
2. isValidMySqlTimeZoneId : replaced Boolean return with True for org/opensearch/sql/utils/DateTimeUtils::isValidMySqlTimeZoneId → KILLED
    return (passedTzValidator.isBefore(maxTzValidator)
114 1 1. isValidMySqlTimeZoneId : negated conditional → KILLED
        || passedTzValidator.isEqual(maxTzValidator))
115 1 1. isValidMySqlTimeZoneId : negated conditional → KILLED
        && (passedTzValidator.isAfter(minTzValidator)
116 1 1. isValidMySqlTimeZoneId : negated conditional → KILLED
        || passedTzValidator.isEqual(minTzValidator));
117
  }
118
}

Mutations

25

1.1
Location : roundFloor
Killed by : org.opensearch.sql.utils.DateTimeUtilsTest.[engine:junit-jupiter]/[class:org.opensearch.sql.utils.DateTimeUtilsTest]/[method:round()]
Replaced long modulus with multiplication → KILLED

2.2
Location : roundFloor
Killed by : org.opensearch.sql.utils.DateTimeUtilsTest.[engine:junit-jupiter]/[class:org.opensearch.sql.utils.DateTimeUtilsTest]/[method:round()]
Replaced long subtraction with addition → KILLED

3.3
Location : roundFloor
Killed by : org.opensearch.sql.utils.DateTimeUtilsTest.[engine:junit-jupiter]/[class:org.opensearch.sql.utils.DateTimeUtilsTest]/[method:round()]
replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundFloor → KILLED

36

1.1
Location : roundWeek
Killed by : none
Replaced long addition with subtraction → SURVIVED

2.2
Location : roundWeek
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:week_span()]
Replaced long multiplication with division → KILLED

3.3
Location : roundWeek
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:week_span()]
Replaced long subtraction with addition → KILLED

4.4
Location : roundWeek
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:week_span()]
replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundWeek → KILLED

50

1.1
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced integer subtraction with addition → KILLED

2.2
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced long multiplication with division → KILLED

51

1.1
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced long addition with subtraction → KILLED

2.2
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced long subtraction with addition → KILLED

52

1.1
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced long division with multiplication → KILLED

2.2
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced long subtraction with addition → KILLED

3.3
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
Replaced long multiplication with division → KILLED

53

1.1
Location : roundMonth
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:month_span()]
replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundMonth → KILLED

65

1.1
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long multiplication with division → KILLED

67

1.1
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced integer subtraction with addition → KILLED

2.2
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long multiplication with division → KILLED

68

1.1
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long addition with subtraction → KILLED

2.2
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long subtraction with addition → KILLED

69

1.1
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long multiplication with division → KILLED

2.2
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long division with multiplication → KILLED

3.3
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long subtraction with addition → KILLED

4.4
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long multiplication with division → KILLED

5.5
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
Replaced long multiplication with division → KILLED

70

1.1
Location : roundQuarter
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:quarter_span()]
replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundQuarter → KILLED

83

1.1
Location : roundYear
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:year_span()]
Replaced integer subtraction with addition → KILLED

84

1.1
Location : roundYear
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:year_span()]
Replaced integer division with multiplication → KILLED

2.2
Location : roundYear
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:year_span()]
Replaced integer multiplication with division → KILLED

85

1.1
Location : roundYear
Killed by : org.opensearch.sql.planner.physical.AggregationOperatorTest.[engine:junit-jupiter]/[class:org.opensearch.sql.planner.physical.AggregationOperatorTest]/[method:year_span()]
replaced long return with 0 for org/opensearch/sql/utils/DateTimeUtils::roundYear → KILLED

113

1.1
Location : isValidMySqlTimeZoneId
Killed by : org.opensearch.sql.expression.datetime.DateTimeTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.datetime.DateTimeTest]/[method:negativeField1WrittenField2()]
negated conditional → KILLED

2.2
Location : isValidMySqlTimeZoneId
Killed by : org.opensearch.sql.expression.datetime.DateTimeTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.datetime.DateTimeTest]/[method:negativeField1PositiveField2()]
replaced Boolean return with True for org/opensearch/sql/utils/DateTimeUtils::isValidMySqlTimeZoneId → KILLED

114

1.1
Location : isValidMySqlTimeZoneId
Killed by : org.opensearch.sql.expression.datetime.DateTimeTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.datetime.DateTimeTest]/[method:negativeField1PositiveField2()]
negated conditional → KILLED

115

1.1
Location : isValidMySqlTimeZoneId
Killed by : org.opensearch.sql.expression.datetime.DateTimeTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.datetime.DateTimeTest]/[method:negativeField1WrittenField2()]
negated conditional → KILLED

116

1.1
Location : isValidMySqlTimeZoneId
Killed by : org.opensearch.sql.expression.datetime.DateTimeTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.datetime.DateTimeTest]/[method:twentyFourHourDifference()]
negated conditional → KILLED

Active mutators

Tests examined


Report generated by PIT 1.9.0