diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java index 98e8f005769..dd1b2ae5324 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/DateExpression.java @@ -20,5 +20,18 @@ * Expresses a date value. */ public interface DateExpression extends Expression { + IntegerExpression year(StringExpression timezone); + IntegerExpression month(StringExpression timezone); + IntegerExpression dayOfMonth(StringExpression timezone); + IntegerExpression dayOfWeek(StringExpression timezone); + IntegerExpression dayOfYear(StringExpression timezone); + IntegerExpression hour(StringExpression timezone); + IntegerExpression minute(StringExpression timezone); + IntegerExpression second(StringExpression timezone); + IntegerExpression week(StringExpression timezone); + IntegerExpression millisecond(StringExpression timezone); + + StringExpression dateToString(); + StringExpression dateToString(StringExpression timezone, StringExpression format); } diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java index 1bb631015f1..28987a8dc01 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/Expressions.java @@ -33,9 +33,7 @@ import java.time.Instant; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; import static com.mongodb.client.model.expressions.MqlExpression.AstPlaceholder; diff --git a/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java b/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java index 218a396b0bc..370f3ce7040 100644 --- a/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java +++ b/driver-core/src/main/com/mongodb/client/model/expressions/MqlExpression.java @@ -332,6 +332,77 @@ public IntegerExpression min(final IntegerExpression i) { return new MqlExpression<>(ast("$min", i)); } + /** @see DateExpression */ + + private MqlExpression usingTimezone(final String name, final StringExpression timezone) { + return new MqlExpression<>((cr) -> astDoc(name, new BsonDocument() + .append("date", this.toBsonValue(cr)) + .append("timezone", extractBsonValue(cr, timezone)))); + } + + @Override + public IntegerExpression year(final StringExpression timezone) { + return usingTimezone("$year", timezone); + } + + @Override + public IntegerExpression month(final StringExpression timezone) { + return usingTimezone("$month", timezone); + } + + @Override + public IntegerExpression dayOfMonth(final StringExpression timezone) { + return usingTimezone("$dayOfMonth", timezone); + } + + @Override + public IntegerExpression dayOfWeek(final StringExpression timezone) { + return usingTimezone("$dayOfWeek", timezone); + } + + @Override + public IntegerExpression dayOfYear(final StringExpression timezone) { + return usingTimezone("$dayOfYear", timezone); + } + + @Override + public IntegerExpression hour(final StringExpression timezone) { + return usingTimezone("$hour", timezone); + } + + @Override + public IntegerExpression minute(final StringExpression timezone) { + return usingTimezone("$minute", timezone); + } + + @Override + public IntegerExpression second(final StringExpression timezone) { + return usingTimezone("$second", timezone); + } + + @Override + public IntegerExpression week(final StringExpression timezone) { + return usingTimezone("$week", timezone); + } + + @Override + public IntegerExpression millisecond(final StringExpression timezone) { + return usingTimezone("$millisecond", timezone); + } + + @Override + public StringExpression dateToString() { + return newMqlExpression((cr) -> astDoc("$dateToString", new BsonDocument() + .append("date", this.toBsonValue(cr)))); + } + + @Override + public StringExpression dateToString(final StringExpression timezone, final StringExpression format) { + return newMqlExpression((cr) -> astDoc("$dateToString", new BsonDocument() + .append("date", this.toBsonValue(cr)) + .append("format", extractBsonValue(cr, format)) + .append("timezone", extractBsonValue(cr, timezone)))); + } /** @see StringExpression */ diff --git a/driver-core/src/test/functional/com/mongodb/client/model/expressions/DateExpressionsFunctionalTest.java b/driver-core/src/test/functional/com/mongodb/client/model/expressions/DateExpressionsFunctionalTest.java new file mode 100644 index 00000000000..73cec9c5198 --- /dev/null +++ b/driver-core/src/test/functional/com/mongodb/client/model/expressions/DateExpressionsFunctionalTest.java @@ -0,0 +1,157 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.expressions; + +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoField; + +import static com.mongodb.client.model.expressions.Expressions.of; +import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; + +class DateExpressionsFunctionalTest extends AbstractExpressionsFunctionalTest { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/#date-expression-operators + + private final Instant instant = Instant.parse("2007-12-03T10:15:30.005Z"); + private final DateExpression date = of(instant); + private final ZonedDateTime utcDateTime = ZonedDateTime.ofInstant(instant, ZoneId.of(ZoneOffset.UTC.getId())); + private final StringExpression utc = of("UTC"); + + @Test + public void literalsTest() { + assertExpression( + instant, + date, + "{'$date': '2007-12-03T10:15:30.005Z'}"); + } + + @Test + public void yearTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/year/ + assertExpression( + utcDateTime.get(ChronoField.YEAR), + date.year(utc), + "{'$year': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void monthTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/month/ + assertExpression( + utcDateTime.get(ChronoField.MONTH_OF_YEAR), + date.month(utc), + "{'$month': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void dayOfMonthTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/dayOfMonth/ + assertExpression( + utcDateTime.get(ChronoField.DAY_OF_MONTH), + date.dayOfMonth(utc), + "{'$dayOfMonth': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void dayOfWeekTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/dayOfWeek/ + assertExpression( + utcDateTime.get(ChronoField.DAY_OF_WEEK) + 1, + date.dayOfWeek(utc), + "{'$dayOfWeek': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void dayOfYearTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/dayOfYear/ + assertExpression( + utcDateTime.get(ChronoField.DAY_OF_YEAR), + date.dayOfYear(utc), + "{'$dayOfYear': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void hourTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/hour/ + assertExpression( + utcDateTime.get(ChronoField.HOUR_OF_DAY), + date.hour(utc), + "{'$hour': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void minuteTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/minute/ + assertExpression( + utcDateTime.get(ChronoField.MINUTE_OF_HOUR), + date.minute(utc), + "{'$minute': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void secondTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/second/ + assertExpression( + utcDateTime.get(ChronoField.SECOND_OF_MINUTE), + date.second(utc), + "{'$second': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void weekTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/week/ + assertExpression( + 48, + date.week(utc), + "{'$week': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void millisecondTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/millisecond/ + assertExpression( + utcDateTime.get(ChronoField.MILLI_OF_SECOND), + date.millisecond(utc), + "{'$millisecond': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, 'timezone': 'UTC'}}"); + } + + @Test + public void dateToStringTest() { + // https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateToString/ + assertExpression( + instant.toString(), + date.dateToString(), + "{'$dateToString': {'date': {'$date': '2007-12-03T10:15:30.005Z'}}}"); + // with parameters + assertExpression( + utcDateTime.withZoneSameInstant(ZoneId.of("America/New_York")).format(ISO_LOCAL_DATE_TIME), + date.dateToString(of("America/New_York"), of("%Y-%m-%dT%H:%M:%S.%L")), + "{'$dateToString': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, " + + "'format': '%Y-%m-%dT%H:%M:%S.%L', " + + "'timezone': 'America/New_York'}}"); + assertExpression( + utcDateTime.withZoneSameInstant(ZoneId.of("+04:30")).format(ISO_LOCAL_DATE_TIME), + date.dateToString(of("+04:30"), of("%Y-%m-%dT%H:%M:%S.%L")), + "{'$dateToString': {'date': {'$date': '2007-12-03T10:15:30.005Z'}, " + + "'format': '%Y-%m-%dT%H:%M:%S.%L', " + + "'timezone': '+04:30'}}"); + } +}