-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Signed-off-by: Yury Fridlyand <[email protected]> Signed-off-by: Yury Fridlyand <[email protected]>
- Loading branch information
1 parent
95a24b2
commit 9f602c3
Showing
13 changed files
with
573 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
174 changes: 174 additions & 0 deletions
174
core/src/test/java/org/opensearch/sql/expression/datetime/MakeDateTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
|
||
package org.opensearch.sql.expression.datetime; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.mockito.Mockito.when; | ||
import static org.opensearch.sql.data.model.ExprValueUtils.missingValue; | ||
import static org.opensearch.sql.data.model.ExprValueUtils.nullValue; | ||
import static org.opensearch.sql.data.type.ExprCoreType.DOUBLE; | ||
|
||
import java.time.LocalDate; | ||
import java.time.Year; | ||
import java.util.List; | ||
import java.util.stream.Stream; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.Arguments; | ||
import org.junit.jupiter.params.provider.MethodSource; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.opensearch.sql.data.model.ExprValue; | ||
import org.opensearch.sql.expression.DSL; | ||
import org.opensearch.sql.expression.Expression; | ||
import org.opensearch.sql.expression.ExpressionTestBase; | ||
import org.opensearch.sql.expression.FunctionExpression; | ||
import org.opensearch.sql.expression.config.ExpressionConfig; | ||
import org.opensearch.sql.expression.env.Environment; | ||
import org.opensearch.sql.expression.function.FunctionName; | ||
import org.opensearch.sql.expression.function.FunctionSignature; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
public class MakeDateTest extends ExpressionTestBase { | ||
|
||
@Mock | ||
Environment<Expression, ExprValue> env; | ||
|
||
@Mock | ||
Expression nullRef; | ||
|
||
@Mock | ||
Expression missingRef; | ||
|
||
private FunctionExpression makedate(Expression year, Expression dayOfYear) { | ||
var repo = new ExpressionConfig().functionRepository(); | ||
var func = repo.resolve(new FunctionSignature(new FunctionName("makedate"), | ||
List.of(DOUBLE, DOUBLE))); | ||
return (FunctionExpression)func.apply(List.of(year, dayOfYear)); | ||
} | ||
|
||
private LocalDate makedate(Double year, Double dayOfYear) { | ||
return makedate(DSL.literal(year), DSL.literal(dayOfYear)).valueOf(null).dateValue(); | ||
} | ||
|
||
@Test | ||
public void checkEdgeCases() { | ||
assertEquals(LocalDate.ofYearDay(2002, 1), makedate(2001., 366.), | ||
"No switch to the next year on getting 366th day of a non-leap year"); | ||
assertEquals(LocalDate.ofYearDay(2005, 1), makedate(2004., 367.), | ||
"No switch to the next year on getting 367th day of a leap year"); | ||
assertEquals(LocalDate.ofYearDay(2000, 42), makedate(0., 42.), | ||
"0 year is not interpreted as 2000 as in MySQL"); | ||
assertEquals(nullValue(), eval(makedate(DSL.literal(-1.), DSL.literal(42.))), | ||
"Negative year doesn't produce NULL"); | ||
assertEquals(nullValue(), eval(makedate(DSL.literal(42.), DSL.literal(-1.))), | ||
"Negative dayOfYear doesn't produce NULL"); | ||
assertEquals(nullValue(), eval(makedate(DSL.literal(42.), DSL.literal(0.))), | ||
"Zero dayOfYear doesn't produce NULL"); | ||
|
||
assertEquals(LocalDate.of(1999, 3, 1), makedate(1999., 60.), | ||
"Got Feb 29th of a non-lear year"); | ||
assertEquals(LocalDate.of(1999, 12, 31), makedate(1999., 365.)); | ||
assertEquals(LocalDate.of(2004, 12, 31), makedate(2004., 366.)); | ||
} | ||
|
||
@Test | ||
public void checkRounding() { | ||
assertEquals(LocalDate.of(42, 1, 1), makedate(42.49, 1.49)); | ||
assertEquals(LocalDate.of(43, 1, 2), makedate(42.50, 1.50)); | ||
} | ||
|
||
@Test | ||
public void checkNullValues() { | ||
when(nullRef.valueOf(env)).thenReturn(nullValue()); | ||
|
||
assertEquals(nullValue(), eval(makedate(nullRef, DSL.literal(42.)))); | ||
assertEquals(nullValue(), eval(makedate(DSL.literal(42.), nullRef))); | ||
assertEquals(nullValue(), eval(makedate(nullRef, nullRef))); | ||
} | ||
|
||
@Test | ||
public void checkMissingValues() { | ||
when(missingRef.valueOf(env)).thenReturn(missingValue()); | ||
|
||
assertEquals(missingValue(), eval(makedate(missingRef, DSL.literal(42.)))); | ||
assertEquals(missingValue(), eval(makedate(DSL.literal(42.), missingRef))); | ||
assertEquals(missingValue(), eval(makedate(missingRef, missingRef))); | ||
} | ||
|
||
private static Stream<Arguments> getTestData() { | ||
return Stream.of( | ||
Arguments.of(3755.421154, 9.300720), | ||
Arguments.of(3416.922084, 850.832172), | ||
Arguments.of(498.717527, 590.831215), | ||
Arguments.of(1255.402786, 846.041171), | ||
Arguments.of(2491.200868, 832.929840), | ||
Arguments.of(1140.775582, 345.592629), | ||
Arguments.of(2087.208382, 110.392189), | ||
Arguments.of(4582.515870, 763.629197), | ||
Arguments.of(1654.431245, 476.360251), | ||
Arguments.of(1342.494306, 70.108352), | ||
Arguments.of(171.841206, 794.470738), | ||
Arguments.of(5000.103926, 441.461842), | ||
Arguments.of(2957.828371, 273.909052), | ||
Arguments.of(2232.699033, 171.537097), | ||
Arguments.of(4650.163672, 226.857148), | ||
Arguments.of(495.943520, 735.062451), | ||
Arguments.of(4568.187019, 552.394124), | ||
Arguments.of(688.085482, 283.574200), | ||
Arguments.of(4627.662672, 791.729059), | ||
Arguments.of(2812.837393, 397.688304), | ||
Arguments.of(3050.030341, 596.714966), | ||
Arguments.of(3617.452566, 619.795467), | ||
Arguments.of(2210.322073, 106.914268), | ||
Arguments.of(675.757974, 147.702828), | ||
Arguments.of(1101.801820, 40.055318) | ||
); | ||
} | ||
|
||
/** | ||
* Test function with given pseudo-random values. | ||
* @param year year | ||
* @param dayOfYear day of year | ||
*/ | ||
@ParameterizedTest(name = "year = {0}, dayOfYear = {1}") | ||
@MethodSource("getTestData") | ||
public void checkRandomValues(double year, double dayOfYear) { | ||
LocalDate actual = makedate(year, dayOfYear); | ||
LocalDate expected = getReferenceValue(year, dayOfYear); | ||
|
||
assertEquals(expected, actual, | ||
String.format("year = %f, dayOfYear = %f", year, dayOfYear)); | ||
} | ||
|
||
/** | ||
* Using another algorithm to get reference value. | ||
* We should go to the next year until remaining @dayOfYear is bigger than 365/366. | ||
* @param year Year. | ||
* @param dayOfYear Day of the year. | ||
* @return The calculated date. | ||
*/ | ||
private LocalDate getReferenceValue(double year, double dayOfYear) { | ||
var yearL = (int)Math.round(year); | ||
var dayL = (int)Math.round(dayOfYear); | ||
while (true) { | ||
int daysInYear = Year.isLeap(yearL) ? 366 : 365; | ||
if (dayL > daysInYear) { | ||
dayL -= daysInYear; | ||
yearL++; | ||
} else { | ||
break; | ||
} | ||
} | ||
return LocalDate.ofYearDay(yearL, dayL); | ||
} | ||
|
||
private ExprValue eval(Expression expression) { | ||
return expression.valueOf(env); | ||
} | ||
} |
Oops, something went wrong.