55
66package org .opensearch .sql .expression .datetime ;
77
8- import static java .time .temporal .ChronoField .ALIGNED_WEEK_OF_YEAR ;
98import static org .junit .jupiter .api .Assertions .assertEquals ;
109import static org .opensearch .sql .data .type .ExprCoreType .LONG ;
1110
11+ import java .time .Instant ;
1212import java .time .LocalDate ;
13+ import java .time .LocalDateTime ;
14+ import java .time .LocalTime ;
15+ import java .time .ZoneId ;
16+ import java .time .temporal .IsoFields ;
1317import java .util .stream .Stream ;
1418import org .junit .jupiter .api .Test ;
1519import org .junit .jupiter .params .ParameterizedTest ;
1620import org .junit .jupiter .params .provider .Arguments ;
1721import org .junit .jupiter .params .provider .MethodSource ;
22+ import org .junit .jupiter .params .provider .ValueSource ;
1823import org .opensearch .sql .data .model .ExprDateValue ;
1924import org .opensearch .sql .data .model .ExprDatetimeValue ;
2025import org .opensearch .sql .data .model .ExprTimeValue ;
2328import org .opensearch .sql .expression .Expression ;
2429import org .opensearch .sql .expression .ExpressionTestBase ;
2530import org .opensearch .sql .expression .FunctionExpression ;
31+ import org .opensearch .sql .expression .function .FunctionProperties ;
2632
2733class ExtractTest extends ExpressionTestBase {
2834
@@ -82,9 +88,14 @@ public void testExtractWithDatetime(String part, long expected) {
8288 }
8389
8490 private void datePartWithTimeArgQuery (String part , String time , long expected ) {
91+ datePartWithTimeArgQuery (functionProperties , part , time , expected );
92+ }
93+
94+ private void datePartWithTimeArgQuery (
95+ FunctionProperties properties , String part , String time , long expected ) {
8596 ExprTimeValue timeValue = new ExprTimeValue (time );
8697 FunctionExpression datetimeExpression =
87- DSL .extract (functionProperties , DSL .literal (part ), DSL .literal (timeValue ));
98+ DSL .extract (properties , DSL .literal (part ), DSL .literal (timeValue ));
8899
89100 assertEquals (LONG , datetimeExpression .type ());
90101 assertEquals (expected , eval (datetimeExpression ).longValue ());
@@ -96,21 +107,49 @@ public void testExtractDatePartWithTimeType() {
96107
97108 datePartWithTimeArgQuery ("DAY" , timeInput , now .getDayOfMonth ());
98109
99- // To avoid flaky test, skip the testing in December and January because the WEEK is ISO 8601
100- // week-of-week-based-year which is considered to start on a Monday and week 1 is the first week
101- // with >3 days. it is possible for early-January dates to be part of the 52nd or 53rd week of
102- // the previous year, and for late-December dates to be part of the first week of the next year.
103- // For example, 2005-01-02 is part of the 53rd week of year 2004, while 2012-12-31 is part of
104- // the first week of 2013
105- if (now .getMonthValue () != 1 && now .getMonthValue () != 12 ) {
106- datePartWithTimeArgQuery ("WEEK" , datetimeInput , now .get (ALIGNED_WEEK_OF_YEAR ));
107- }
108-
109110 datePartWithTimeArgQuery ("MONTH" , timeInput , now .getMonthValue ());
110111
111112 datePartWithTimeArgQuery ("YEAR" , timeInput , now .getYear ());
112113 }
113114
115+ @ ParameterizedTest (name = "{0}" )
116+ @ ValueSource (
117+ strings = {
118+ "2009-12-26" ,
119+ "2009-12-27" ,
120+ "2008-12-28" , // Week 52 of week-based-year 2008
121+ "2009-12-29" ,
122+ "2008-12-29" , // Week 1 of week-based-year 2009
123+ "2008-12-31" , // Week 1 of week-based-year 2009
124+ "2009-01-01" , // Week 1 of week-based-year 2009
125+ "2009-01-04" , // Week 1 of week-based-year 2009
126+ "2009-01-05" , // Week 2 of week-based-year 2009
127+ "2025-12-27" , // year with 52 weeks
128+ "2026-01-01" , // year starts on a THURSDAY
129+ "2028-12-30" , // year with 53 weeks
130+ "2028-12-31" , // year starts in December
131+ "2029-01-01" ,
132+ "2033-12-31" , // year with 53 weeks
133+ "2034-01-01" , // January 1st on a SUNDAY
134+ "2034-12-30" , // year with 52 weeks
135+ "2034-12-31"
136+ })
137+ public void testExtractWeekPartWithTimeType (String arg ) {
138+
139+ // setup default date/time properties for the extract function
140+ ZoneId currentZoneId = ZoneId .systemDefault ();
141+ Instant nowInstant =
142+ LocalDate .parse (arg ).atTime (LocalTime .parse (timeInput )).atZone (currentZoneId ).toInstant ();
143+ FunctionProperties properties = new FunctionProperties (nowInstant , currentZoneId );
144+
145+ // Expected WEEK value should be formated from week-of-week-based-year
146+ LocalDateTime localDateTime = LocalDateTime .ofInstant (nowInstant , currentZoneId );
147+ int expected = localDateTime .get (IsoFields .WEEK_OF_WEEK_BASED_YEAR );
148+
149+ // verify
150+ datePartWithTimeArgQuery (properties , "WEEK" , timeInput , expected );
151+ }
152+
114153 @ ParameterizedTest (name = "{0}" )
115154 @ MethodSource ("getDateResultsForExtractFunction" )
116155 public void testExtractWithDate (String part , long expected ) {
0 commit comments