DateOperators.java
/*
* Copyright 2016-present the original author or authors.
*
* 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
*
* https://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 org.springframework.data.mongodb.core.aggregation;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Gateway to {@literal Date} aggregation operations.
*
* @author Christoph Strobl
* @author Matt Morrissette
* @since 1.10
*/
public class DateOperators {
/**
* Take the date referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateOperatorFactory}.
*/
public static DateOperatorFactory dateOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return new DateOperatorFactory(fieldReference);
}
/**
* Take the date referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateOperatorFactory}.
* @since 3.3
*/
public static DateOperatorFactory zonedDateOf(String fieldReference, Timezone timezone) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return new DateOperatorFactory(fieldReference).withTimezone(timezone);
}
/**
* Take the date resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateOperatorFactory}.
*/
public static DateOperatorFactory dateOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return new DateOperatorFactory(expression);
}
/**
* Take the date resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateOperatorFactory}.
* @since 3.3
*/
public static DateOperatorFactory zonedDateOf(AggregationExpression expression, Timezone timezone) {
Assert.notNull(expression, "Expression must not be null");
return new DateOperatorFactory(expression).withTimezone(timezone);
}
/**
* Take the given value as date. <br />
* This can be one of:
* <ul>
* <li>{@link java.util.Date}</li>
* <li>{@link java.util.Calendar}</li>
* <li>{@link java.time.Instant}</li>
* <li>{@link java.time.ZonedDateTime}</li>
* <li>{@link java.lang.Long}</li>
* <li>{@link Field}</li>
* <li>{@link AggregationExpression}</li>
* </ul>
*
* @param value must not be {@literal null}.
* @return new instance of {@link DateOperatorFactory}.
* @since 2.1
*/
public static DateOperatorFactory dateValue(Object value) {
Assert.notNull(value, "Value must not be null");
return new DateOperatorFactory(value);
}
/**
* Construct a Date object by providing the date���s constituent properties.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @return new instance of {@link DateFromPartsOperatorFactory}.
* @since 2.1
*/
public static DateFromPartsOperatorFactory dateFromParts() {
return new DateFromPartsOperatorFactory(Timezone.none());
}
/**
* Construct a Date object from the given date {@link String}.<br />
* To use a {@link Field field reference} or {@link AggregationExpression} as source of the date string consider
* {@link DateOperatorFactory#fromString()} or {@link DateFromString#fromStringOf(AggregationExpression)}.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @return new instance of {@link DateFromPartsOperatorFactory}.
* @since 2.1
*/
public static DateFromString dateFromString(String value) {
return DateFromString.fromString(value);
}
/**
* Timezone represents a MongoDB timezone abstraction which can be represented with a timezone ID or offset as a
* {@link String}. Also accepts a {@link AggregationExpression} or {@link Field} that resolves to a {@link String} of
* either Olson Timezone Identifier or a UTC Offset.<br />
* <table>
* <tr>
* <th>Format</th>
* <th>Example</th>
* </tr>
* <tr>
* <td>Olson Timezone Identifier</td>
* <td>"America/New_York"<br />
* "Europe/London"<br />
* "GMT"</td>
* </tr>
* <tr>
* <td>UTC Offset</td>
* <td>+/-[hh]:[mm], e.g. "+04:45"<br />
* -[hh][mm], e.g. "-0530"<br />
* +/-[hh], e.g. "+03"</td>
* </tr>
* </table>
* <strong>NOTE:</strong> Support for timezones in aggregations Requires MongoDB 3.6 or later.
*
* @author Christoph Strobl
* @author Mark Paluch
* @since 2.1
*/
public static class Timezone {
private static final Timezone NONE = new Timezone(null);
private final @Nullable Object value;
private Timezone(@Nullable Object value) {
this.value = value;
}
/**
* Return an empty {@link Timezone}.
*
* @return never {@literal null}.
*/
public static Timezone none() {
return NONE;
}
/**
* Create a {@link Timezone} for the given value which must be a valid expression that resolves to a {@link String}
* representing an Olson Timezone Identifier or UTC Offset.
*
* @param value the plain timezone {@link String}, a {@link Field} holding the timezone or an
* {@link AggregationExpression} resulting in the timezone.
* @return new instance of {@link Timezone}.
*/
public static Timezone valueOf(Object value) {
Assert.notNull(value, "Value must not be null");
return new Timezone(value);
}
/**
* Create a {@link Timezone} for the given {@link TimeZone} rendering the offset as UTC offset.
*
* @param timeZone {@link TimeZone} rendering the offset as UTC offset.
* @return new instance of {@link Timezone}.
* @since 3.3
*/
public static Timezone fromOffset(TimeZone timeZone) {
Assert.notNull(timeZone, "TimeZone must not be null");
return fromOffset(
ZoneOffset.ofTotalSeconds(Math.toIntExact(TimeUnit.MILLISECONDS.toSeconds(timeZone.getRawOffset()))));
}
/**
* Create a {@link Timezone} for the given {@link ZoneOffset} rendering the offset as UTC offset.
*
* @param offset {@link ZoneOffset} rendering the offset as UTC offset.
* @return new instance of {@link Timezone}.
* @since 3.3
*/
public static Timezone fromOffset(ZoneOffset offset) {
Assert.notNull(offset, "ZoneOffset must not be null");
return new Timezone(offset.toString());
}
/**
* Create a {@link Timezone} for the given {@link TimeZone} rendering the offset as UTC offset.
*
* @param timeZone {@link Timezone} rendering the offset as zone identifier.
* @return new instance of {@link Timezone}.
* @since 3.3
*/
public static Timezone fromZone(TimeZone timeZone) {
Assert.notNull(timeZone, "TimeZone must not be null");
return valueOf(timeZone.getID());
}
/**
* Create a {@link Timezone} for the given {@link java.time.ZoneId} rendering the offset as UTC offset.
*
* @param zoneId {@link ZoneId} rendering the offset as zone identifier.
* @return new instance of {@link Timezone}.
* @since 3.3
*/
public static Timezone fromZone(ZoneId zoneId) {
Assert.notNull(zoneId, "ZoneId must not be null");
return new Timezone(zoneId.toString());
}
/**
* Create a {@link Timezone} for the {@link Field} reference holding the Olson Timezone Identifier or UTC Offset.
*
* @param fieldReference the {@link Field} holding the timezone.
* @return new instance of {@link Timezone}.
*/
public static Timezone ofField(String fieldReference) {
return valueOf(Fields.field(fieldReference));
}
/**
* Create a {@link Timezone} for the {@link AggregationExpression} resulting in the Olson Timezone Identifier or UTC
* Offset.
*
* @param expression the {@link AggregationExpression} resulting in the timezone.
* @return new instance of {@link Timezone}.
*/
public static Timezone ofExpression(AggregationExpression expression) {
return valueOf(expression);
}
@Nullable
Object getValue() {
return value;
}
}
/**
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class DateOperatorFactory {
private final @Nullable String fieldReference;
private final @Nullable Object dateValue;
private final @Nullable AggregationExpression expression;
private final Timezone timezone;
/**
* @param fieldReference
* @param expression
* @param value
* @param timezone
* @since 2.1
*/
private DateOperatorFactory(@Nullable String fieldReference, @Nullable AggregationExpression expression,
@Nullable Object value, Timezone timezone) {
this.fieldReference = fieldReference;
this.expression = expression;
this.dateValue = value;
this.timezone = timezone;
}
/**
* Creates new {@link DateOperatorFactory} for given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
*/
public DateOperatorFactory(String fieldReference) {
this(fieldReference, null, null, Timezone.none());
Assert.notNull(fieldReference, "FieldReference must not be null");
}
/**
* Creates new {@link DateOperatorFactory} for given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
*/
public DateOperatorFactory(AggregationExpression expression) {
this(null, expression, null, Timezone.none());
Assert.notNull(expression, "Expression must not be null");
}
/**
* Creates new {@link DateOperatorFactory} for given {@code value} that resolves to a Date. <br />
* <ul>
* <li>{@link java.util.Date}</li>
* <li>{@link java.util.Calendar}</li>
* <li>{@link java.time.Instant}</li>
* <li>{@link java.time.ZonedDateTime}</li>
* <li>{@link java.lang.Long}</li>
* </ul>
*
* @param value must not be {@literal null}.
* @since 2.1
*/
public DateOperatorFactory(Object value) {
this(null, null, value, Timezone.none());
Assert.notNull(value, "Value must not be null");
}
/**
* Create a new {@link DateOperatorFactory} bound to a given {@link Timezone}.<br />
* <strong>NOTE:</strong> Requires Mongo 3.6 or later.
*
* @param timezone must not be {@literal null}. Use {@link Timezone#none()} instead.
* @return new instance of {@link DateOperatorFactory}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
public DateOperatorFactory withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new DateOperatorFactory(fieldReference, expression, dateValue, timezone);
}
/**
* Creates new {@link AggregationExpression} that adds the value of the given {@link AggregationExpression
* expression} (in {@literal units}).
*
* @param expression must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateAdd addValueOf(AggregationExpression expression, String unit) {
return applyTimezone(DateAdd.addValueOf(expression, unit).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that adds the value of the given {@link AggregationExpression
* expression} (in {@literal units}).
*
* @param expression must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateAdd addValueOf(AggregationExpression expression, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(DateAdd.addValueOf(expression, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()),
timezone);
}
/**
* Creates new {@link AggregationExpression} that adds the value stored at the given {@literal field} (in
* {@literal units}).
*
* @param fieldReference must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateAdd addValueOf(String fieldReference, String unit) {
return applyTimezone(DateAdd.addValueOf(fieldReference, unit).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that adds the value stored at the given {@literal field} (in
* {@literal units}).
*
* @param fieldReference must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateAdd addValueOf(String fieldReference, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(
DateAdd.addValueOf(fieldReference, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that adds the given value (in {@literal units}).
*
* @param value must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return
* @since 3.3 new instance of {@link DateAdd}.
*/
public DateAdd add(Object value, String unit) {
return applyTimezone(DateAdd.addValue(value, unit).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that adds the given value (in {@literal units}).
*
* @param value must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return
* @since 3.3 new instance of {@link DateAdd}.
*/
public DateAdd add(Object value, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(DateAdd.addValue(value, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()),
timezone);
}
/**
* Creates new {@link AggregationExpression} that subtracts the value of the given {@link AggregationExpression
* expression} (in {@literal units}).
*
* @param expression must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
* @since 4.0
*/
public DateSubtract subtractValueOf(AggregationExpression expression, String unit) {
return applyTimezone(DateSubtract.subtractValueOf(expression, unit).fromDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that subtracts the value of the given {@link AggregationExpression
* expression} (in {@literal units}).
*
* @param expression must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
* @since 4.0
*/
public DateSubtract subtractValueOf(AggregationExpression expression, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(
DateSubtract.subtractValueOf(expression, unit.name().toLowerCase(Locale.ROOT)).fromDate(dateReference()),
timezone);
}
/**
* Creates new {@link AggregationExpression} that subtracts the value stored at the given {@literal field} (in
* {@literal units}).
*
* @param fieldReference must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
* @since 4.0
*/
public DateSubtract subtractValueOf(String fieldReference, String unit) {
return applyTimezone(DateSubtract.subtractValueOf(fieldReference, unit).fromDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that subtracts the value stored at the given {@literal field} (in
* {@literal units}).
*
* @param fieldReference must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
* @since 4.0
*/
public DateSubtract subtractValueOf(String fieldReference, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(
DateSubtract.subtractValueOf(fieldReference, unit.name().toLowerCase(Locale.ROOT)).fromDate(dateReference()),
timezone);
}
/**
* Creates new {@link AggregationExpression} that subtracts the given value (in {@literal units}).
*
* @param value must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
* @since 4.0
*/
public DateSubtract subtract(Object value, String unit) {
return applyTimezone(DateSubtract.subtractValue(value, unit).fromDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that subtracts the given value (in {@literal units}).
*
* @param value must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
* @since 4.0
*/
public DateSubtract subtract(Object value, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(
DateSubtract.subtractValue(value, unit.name().toLowerCase(Locale.ROOT)).fromDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that truncates a date to the given {@literal unit}.
*
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
* @since 4.0
*/
public DateTrunc truncate(String unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(DateTrunc.truncateValue(dateReference()).to(unit), timezone);
}
/**
* Creates new {@link AggregationExpression} that truncates a date to the given {@literal unit}.
*
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
* @since 4.0
*/
public DateTrunc truncate(TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return truncate(unit.name().toLowerCase(Locale.ROOT));
}
/**
* Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and
* 366.
*
* @return new instance of {@link DayOfYear}.
*/
public DayOfYear dayOfYear() {
return applyTimezone(DayOfYear.dayOfYear(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the day of the month for a date as a number between 1 and
* 31.
*
* @return new instance of {@link DayOfMonth}.
*/
public DayOfMonth dayOfMonth() {
return applyTimezone(DayOfMonth.dayOfMonth(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the day of the week for a date as a number between 1
* (Sunday) and 7 (Saturday).
*
* @return new instance of {@link DayOfWeek}.
*/
public DayOfWeek dayOfWeek() {
return applyTimezone(DayOfWeek.dayOfWeek(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date
* computed by the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateDiff diffValueOf(AggregationExpression expression, String unit) {
return applyTimezone(DateDiff.diffValueOf(expression, unit).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date
* computed by the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateDiff diffValueOf(AggregationExpression expression, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(
DateDiff.diffValueOf(expression, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date stored
* at the given {@literal field}.
*
* @param fieldReference must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateDiff diffValueOf(String fieldReference, String unit) {
return applyTimezone(DateDiff.diffValueOf(fieldReference, unit).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date stored
* at the given {@literal field}.
*
* @param fieldReference must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateDiff diffValueOf(String fieldReference, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(
DateDiff.diffValueOf(fieldReference, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date given
* {@literal value}.
*
* @param value anything the resolves to a valid date. Must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateDiff diff(Object value, String unit) {
return applyTimezone(DateDiff.diffValue(value, unit).toDate(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date given
* {@literal value}.
*
* @param value anything the resolves to a valid date. Must not be {@literal null}.
* @param unit the unit of measure. Must not be {@literal null}.
* @return new instance of {@link DateAdd}. @since 3.3
*/
public DateDiff diff(Object value, TemporalUnit unit) {
Assert.notNull(unit, "TemporalUnit must not be null");
return applyTimezone(DateDiff.diffValue(value, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()),
timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the year portion of a date.
*
* @return new instance of {@link Year}.
*/
public Year year() {
return applyTimezone(Year.year(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the month of a date as a number between 1 and 12.
*
* @return new instance of {@link Month}.
*/
public Month month() {
return applyTimezone(Month.month(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the week of the year for a date as a number between 0 and
* 53.
*
* @return new instance of {@link Week}.
*/
public Week week() {
return applyTimezone(Week.week(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the hour portion of a date as a number between 0 and 23.
*
* @return new instance of {@link Hour}.
*/
public Hour hour() {
return applyTimezone(Hour.hour(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the minute portion of a date as a number between 0 and 59.
*
* @return new instance of {@link Minute}.
*/
public Minute minute() {
return applyTimezone(Minute.minute(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the second portion of a date as a number between 0 and 59,
* but can be 60 to account for leap seconds.
*
* @return new instance of {@link Second}.
*/
public Second second() {
return applyTimezone(Second.second(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the millisecond portion of a date as an integer between 0
* and 999.
*
* @return new instance of {@link Millisecond}.
*/
public Millisecond millisecond() {
return applyTimezone(Millisecond.millisecond(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that converts a date object to a string according to a user-specified
* {@literal format}.
*
* @param format must not be {@literal null}.
* @return new instance of {@link DateToString}.
*/
public DateToString toString(String format) {
return applyTimezone(DateToString.dateToString(dateReference()).toString(format), timezone);
}
/**
* Creates new {@link AggregationExpression} that converts a date object to a string according to the server default
* format.
*
* @return new instance of {@link DateToString}.
* @since 2.1
*/
public DateToString toStringWithDefaultFormat() {
return applyTimezone(DateToString.dateToString(dateReference()).defaultFormat(), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the weekday number in ISO 8601-2018 format, ranging from 1
* (for Monday) to 7 (for Sunday).
*
* @return new instance of {@link IsoDayOfWeek}.
*/
public IsoDayOfWeek isoDayOfWeek() {
return applyTimezone(IsoDayOfWeek.isoDayWeek(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the week number in ISO 8601-2018 format, ranging from 1 to
* 53.
*
* @return new instance of {@link IsoWeek}.
*/
public IsoWeek isoWeek() {
return applyTimezone(IsoWeek.isoWeek(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the year number in ISO 8601-2018 format.
*
* @return new instance of {@link IsoWeekYear}.
*/
public IsoWeekYear isoWeekYear() {
return applyTimezone(IsoWeekYear.isoWeekYear(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns a document containing the constituent parts of the date as
* individual properties.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @return new instance of {@link DateToParts}.
* @since 2.1
*/
public DateToParts toParts() {
return applyTimezone(DateToParts.dateToParts(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that converts a date/time string to a date object.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @return new instance of {@link DateFromString}.
* @since 2.1
*/
public DateFromString fromString() {
return applyTimezone(DateFromString.fromString(dateReference()), timezone);
}
/**
* Creates new {@link AggregationExpression} that returns the incrementing ordinal from a timestamp.
*
* @return new instance of {@link TsIncrement}.
* @since 4.0
*/
public TsIncrement tsIncrement() {
if (timezone != null && !Timezone.none().equals(timezone)) {
throw new IllegalArgumentException("$tsIncrement does not support timezones");
}
return TsIncrement.tsIncrement(dateReference());
}
/**
* Creates new {@link AggregationExpression} that returns the seconds from a timestamp.
*
* @return new instance of {@link TsIncrement}.
* @since 4.0
*/
public TsSecond tsSecond() {
if (timezone != null && !Timezone.none().equals(timezone)) {
throw new IllegalArgumentException("$tsSecond does not support timezones");
}
return TsSecond.tsSecond(dateReference());
}
@SuppressWarnings("NullAway")
private Object dateReference() {
if (usesFieldRef()) {
return Fields.field(fieldReference);
}
return usesExpression() ? expression : dateValue;
}
private boolean usesFieldRef() {
return fieldReference != null;
}
private boolean usesExpression() {
return expression != null;
}
}
/**
* @author Matt Morrissette
* @author Christoph Strobl
* @since 2.1
*/
public static class DateFromPartsOperatorFactory {
private final Timezone timezone;
private DateFromPartsOperatorFactory(Timezone timezone) {
this.timezone = timezone;
}
/**
* Set the {@literal week date year} to the given value which must resolve to a weekday in range {@code 0 - 9999}.
* Can be a simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param isoWeekYear must not be {@literal null}.
* @return new instance of {@link IsoDateFromParts} with {@link Timezone} if set.
* @throws IllegalArgumentException if given {@literal isoWeekYear} is {@literal null}.
*/
public IsoDateFromParts isoWeekYear(Object isoWeekYear) {
return applyTimezone(IsoDateFromParts.dateFromParts().isoWeekYear(isoWeekYear), timezone);
}
/**
* Set the {@literal week date year} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link IsoDateFromParts} with {@link Timezone} if set.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
public IsoDateFromParts isoWeekYearOf(String fieldReference) {
return isoWeekYear(Fields.field(fieldReference));
}
/**
* Set the {@literal week date year} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link IsoDateFromParts} with {@link Timezone} if set.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
public IsoDateFromParts isoWeekYearOf(AggregationExpression expression) {
return isoWeekYear(expression);
}
/**
* Set the {@literal year} to the given value which must resolve to a calendar year. Can be a simple value,
* {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param year must not be {@literal null}.
* @return new instance of {@link DateFromParts} with {@link Timezone} if set.
* @throws IllegalArgumentException if given {@literal year} is {@literal null}
*/
public DateFromParts year(Object year) {
return applyTimezone(DateFromParts.dateFromParts().year(year), timezone);
}
/**
* Set the {@literal year} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateFromParts} with {@link Timezone} if set.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
public DateFromParts yearOf(String fieldReference) {
return year(Fields.field(fieldReference));
}
/**
* Set the {@literal year} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateFromParts} with {@link Timezone} if set.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
public DateFromParts yearOf(AggregationExpression expression) {
return year(expression);
}
/**
* Create a new {@link DateFromPartsOperatorFactory} bound to a given {@link Timezone}.<br />
*
* @param timezone must not be {@literal null}. Use {@link Timezone#none()} instead.
* @return new instance of {@link DateFromPartsOperatorFactory}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
*/
public DateFromPartsOperatorFactory withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new DateFromPartsOperatorFactory(timezone);
}
}
/**
* {@link AggregationExpression} capable of setting a given {@link Timezone}.
*
* @author Christoph Strobl
* @since 2.1
*/
public static abstract class TimezonedDateAggregationExpression extends AbstractAggregationExpression {
protected TimezonedDateAggregationExpression(Object value) {
super(value);
}
/**
* Append the {@code timezone} to a given source. The source itself can be a {@link Map} of already set properties
* or a single value. In case of single value {@code source} the value will be added as {@code date} property.
*
* @param source must not be {@literal null}.
* @param timezone must not be {@literal null} use {@link Timezone#none()} instead.
* @return
*/
protected static java.util.Map<String, Object> appendTimezone(Object source, Timezone timezone) {
java.util.Map<String, Object> args;
if (source instanceof Map map) {
args = new LinkedHashMap<>(map);
} else {
args = new LinkedHashMap<>(2);
args.put("date", source);
}
if (!ObjectUtils.nullSafeEquals(Timezone.none(), timezone)) {
args.put("timezone", timezone.value);
} else if (args.containsKey("timezone")) {
args.remove("timezone");
}
return args;
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
*/
protected abstract TimezonedDateAggregationExpression withTimezone(Timezone timezone);
protected boolean hasTimezone() {
return contains("timezone");
}
}
/**
* {@link AggregationExpression} for {@code $dayOfYear}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class DayOfYear extends TimezonedDateAggregationExpression {
private DayOfYear(Object value) {
super(value);
}
/**
* Creates new {@link DayOfYear}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link DayOfYear}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static DayOfYear dayOfYear(Object value) {
Assert.notNull(value, "value must not be null");
return new DayOfYear(value);
}
/**
* Creates new {@link DayOfYear}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DayOfYear}.
*/
public static DayOfYear dayOfYear(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return dayOfYear(Fields.field(fieldReference));
}
/**
* Creates new {@link DayOfYear}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DayOfYear}.
*/
public static DayOfYear dayOfYear(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return dayOfYear((Object) expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DayOfYear}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public DayOfYear withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new DayOfYear(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dayOfYear";
}
}
/**
* {@link AggregationExpression} for {@code $dayOfMonth}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class DayOfMonth extends TimezonedDateAggregationExpression {
private DayOfMonth(Object value) {
super(value);
}
/**
* Creates new {@link DayOfMonth}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link DayOfMonth}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static DayOfMonth dayOfMonth(Object value) {
Assert.notNull(value, "value must not be null");
return new DayOfMonth(value);
}
/**
* Creates new {@link DayOfMonth}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DayOfMonth}.
*/
public static DayOfMonth dayOfMonth(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return dayOfMonth(Fields.field(fieldReference));
}
/**
* Creates new {@link DayOfMonth}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DayOfMonth}.
*/
public static DayOfMonth dayOfMonth(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return dayOfMonth((Object) expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DayOfMonth}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public DayOfMonth withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new DayOfMonth(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dayOfMonth";
}
}
/**
* {@link AggregationExpression} for {@code $dayOfWeek}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class DayOfWeek extends TimezonedDateAggregationExpression {
private DayOfWeek(Object value) {
super(value);
}
/**
* Creates new {@link DayOfWeek}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link DayOfWeek}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static DayOfWeek dayOfWeek(Object value) {
Assert.notNull(value, "value must not be null");
return new DayOfWeek(value);
}
/**
* Creates new {@link DayOfWeek}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DayOfWeek}.
*/
public static DayOfWeek dayOfWeek(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return dayOfWeek(Fields.field(fieldReference));
}
/**
* Creates new {@link DayOfWeek}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DayOfWeek}.
*/
public static DayOfWeek dayOfWeek(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return dayOfWeek((Object) expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DayOfWeek}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public DayOfWeek withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new DayOfWeek(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dayOfWeek";
}
}
/**
* {@link AggregationExpression} for {@code $year}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Year extends TimezonedDateAggregationExpression {
private Year(Object value) {
super(value);
}
/**
* Creates new {@link Year}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Year}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Year year(Object value) {
Assert.notNull(value, "value must not be null");
return new Year(value);
}
/**
* Creates new {@link Year}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Year}.
*/
public static Year yearOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return year(Fields.field(fieldReference));
}
/**
* Creates new {@link Year}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Year}.
*/
public static Year yearOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return year(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Year}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Year withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Year(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$year";
}
}
/**
* {@link AggregationExpression} for {@code $month}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Month extends TimezonedDateAggregationExpression {
private Month(Object value) {
super(value);
}
/**
* Creates new {@link Month}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Month}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Month month(Object value) {
Assert.notNull(value, "value must not be null");
return new Month(value);
}
/**
* Creates new {@link Month}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Month}.
*/
public static Month monthOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return month(Fields.field(fieldReference));
}
/**
* Creates new {@link Month}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Month}.
*/
public static Month monthOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return month(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Month}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Month withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Month(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$month";
}
}
/**
* {@link AggregationExpression} for {@code $week}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Week extends TimezonedDateAggregationExpression {
private Week(Object value) {
super(value);
}
/**
* Creates new {@link Week}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Week}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Week week(Object value) {
Assert.notNull(value, "value must not be null");
return new Week(value);
}
/**
* Creates new {@link Week}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Week}.
*/
public static Week weekOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return week(Fields.field(fieldReference));
}
/**
* Creates new {@link Week}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Week}.
*/
public static Week weekOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return week(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Week}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Week withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Week(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$week";
}
}
/**
* {@link AggregationExpression} for {@code $hour}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Hour extends TimezonedDateAggregationExpression {
private Hour(Object value) {
super(value);
}
/**
* Creates new {@link Hour}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Hour}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Hour hour(Object value) {
Assert.notNull(value, "value must not be null");
return new Hour(value);
}
/**
* Creates new {@link Hour}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Hour}.
*/
public static Hour hourOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return hour(Fields.field(fieldReference));
}
/**
* Creates new {@link Hour}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Hour}.
*/
public static Hour hourOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return hour(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Hour}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Hour withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Hour(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$hour";
}
}
/**
* {@link AggregationExpression} for {@code $minute}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Minute extends TimezonedDateAggregationExpression {
private Minute(Object value) {
super(value);
}
/**
* Creates new {@link Minute}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Minute}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Minute minute(Object value) {
Assert.notNull(value, "value must not be null");
return new Minute(value);
}
/**
* Creates new {@link Minute}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Minute}.
*/
public static Minute minuteOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return minute(Fields.field(fieldReference));
}
/**
* Creates new {@link Minute}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Minute}.
*/
public static Minute minuteOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return minute(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Minute}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Minute withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Minute(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$minute";
}
}
/**
* {@link AggregationExpression} for {@code $second}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Second extends TimezonedDateAggregationExpression {
private Second(Object value) {
super(value);
}
/**
* Creates new {@link Second}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Second}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Second second(Object value) {
Assert.notNull(value, "value must not be null");
return new Second(value);
}
/**
* Creates new {@link Second}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Second}.
*/
public static Second secondOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return second(Fields.field(fieldReference));
}
/**
* Creates new {@link Second}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Second}.
*/
public static Second secondOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return second(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Second}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Second withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Second(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$second";
}
}
/**
* {@link AggregationExpression} for {@code $millisecond}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class Millisecond extends TimezonedDateAggregationExpression {
private Millisecond(Object value) {
super(value);
}
/**
* Creates new {@link Millisecond}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link Millisecond}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static Millisecond millisecond(Object value) {
Assert.notNull(value, "value must not be null");
return new Millisecond(value);
}
/**
* Creates new {@link Millisecond}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Millisecond}.
*/
public static Millisecond millisecondOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return millisecond(Fields.field(fieldReference));
}
/**
* Creates new {@link Millisecond}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Millisecond}.
*/
public static Millisecond millisecondOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return millisecond(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Millisecond}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public Millisecond withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new Millisecond(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$millisecond";
}
}
/**
* {@link AggregationExpression} for {@code $dateToString}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class DateToString extends TimezonedDateAggregationExpression {
private DateToString(Object value) {
super(value);
}
/**
* Creates new {@link FormatBuilder}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link FormatBuilder}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static FormatBuilder dateToString(Object value) {
Assert.notNull(value, "value must not be null");
return new FormatBuilder() {
@Override
public DateToString toString(String format) {
Assert.notNull(format, "Format must not be null");
return new DateToString(argumentMap(value, format, Timezone.none()));
}
@Override
public DateToString defaultFormat() {
return new DateToString(argumentMap(value, null, Timezone.none()));
}
};
}
/**
* Creates new {@link FormatBuilder} allowing to define the date format to apply.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link FormatBuilder} to crate {@link DateToString}.
*/
public static FormatBuilder dateOf(final String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return dateToString(Fields.field(fieldReference));
}
/**
* Creates new {@link FormatBuilder} allowing to define the date format to apply.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link FormatBuilder} to crate {@link DateToString}.
*/
public static FormatBuilder dateOf(final AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return dateToString(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link Millisecond}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public DateToString withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new DateToString(append("timezone", timezone));
}
/**
* Optionally specify the value to return when the date is {@literal null} or missing. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param value must not be {@literal null}.
* @return new instance of {@link DateToString}.
* @since 2.1
*/
@Contract("_ -> new")
public DateToString onNullReturn(Object value) {
return new DateToString(append("onNull", value));
}
/**
* Optionally specify the field holding the value to return when the date is {@literal null} or missing. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateToString}.
* @since 2.1
*/
@Contract("_ -> new")
public DateToString onNullReturnValueOf(String fieldReference) {
return onNullReturn(Fields.field(fieldReference));
}
/**
* Optionally specify the expression to evaluate and return when the date is {@literal null} or missing. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateToString}.
* @since 2.1
*/
@Contract("_ -> new")
public DateToString onNullReturnValueOf(AggregationExpression expression) {
return onNullReturn(expression);
}
@Override
protected String getMongoMethod() {
return "$dateToString";
}
private static java.util.Map<String, Object> argumentMap(Object date, @Nullable String format, Timezone timezone) {
java.util.Map<String, Object> args = new LinkedHashMap<>(2);
if (StringUtils.hasText(format)) {
args.put("format", format);
}
args.put("date", date);
if (!ObjectUtils.nullSafeEquals(timezone, Timezone.none())) {
args.put("timezone", timezone.value);
}
return args;
}
protected java.util.Map<String, Object> append(String key, Object value) {
java.util.Map<String, Object> clone = new LinkedHashMap<>(argumentMap());
if (value instanceof Timezone timezone) {
if (ObjectUtils.nullSafeEquals(value, Timezone.none())) {
clone.remove("timezone");
} else {
clone.put("timezone", timezone.value);
}
} else {
clone.put(key, value);
}
return clone;
}
public interface FormatBuilder {
/**
* Creates new {@link DateToString} with all previously added arguments appending the given one.
*
* @param format must not be {@literal null}.
* @return
*/
DateToString toString(String format);
/**
* Creates new {@link DateToString} using the server default string format ({@code %Y-%m-%dT%H:%M:%S.%LZ}) for
* dates. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @return new instance of {@link DateToString}.
* @since 2.1
*/
DateToString defaultFormat();
}
}
/**
* {@link AggregationExpression} for {@code $isoDayOfWeek}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class IsoDayOfWeek extends TimezonedDateAggregationExpression {
private IsoDayOfWeek(Object value) {
super(value);
}
/**
* Creates new {@link IsoDayOfWeek}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link IsoDayOfWeek}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static IsoDayOfWeek isoDayWeek(Object value) {
Assert.notNull(value, "value must not be null");
return new IsoDayOfWeek(value);
}
/**
* Creates new {@link IsoDayOfWeek}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link IsoDayOfWeek}.
*/
public static IsoDayOfWeek isoDayOfWeek(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return isoDayWeek(Fields.field(fieldReference));
}
/**
* Creates new {@link IsoDayOfWeek}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link IsoDayOfWeek}.
*/
public static IsoDayOfWeek isoDayOfWeek(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return isoDayWeek(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link IsoDayOfWeek}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public IsoDayOfWeek withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new IsoDayOfWeek(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$isoDayOfWeek";
}
}
/**
* {@link AggregationExpression} for {@code $isoWeek}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class IsoWeek extends TimezonedDateAggregationExpression {
private IsoWeek(Object value) {
super(value);
}
/**
* Creates new {@link IsoWeek}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link IsoWeek}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static IsoWeek isoWeek(Object value) {
Assert.notNull(value, "value must not be null");
return new IsoWeek(value);
}
/**
* Creates new {@link IsoWeek}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link IsoWeek}.
*/
public static IsoWeek isoWeekOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return isoWeek(Fields.field(fieldReference));
}
/**
* Creates new {@link IsoWeek}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link IsoWeek}.
*/
public static IsoWeek isoWeekOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return isoWeek(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link IsoWeek}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public IsoWeek withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new IsoWeek(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$isoWeek";
}
}
/**
* {@link AggregationExpression} for {@code $isoWeekYear}.
*
* @author Christoph Strobl
* @author Matt Morrissette
*/
public static class IsoWeekYear extends TimezonedDateAggregationExpression {
private IsoWeekYear(Object value) {
super(value);
}
/**
* Creates new {@link IsoWeekYear}.
*
* @param value must not be {@literal null} and resolve to field, expression or object that represents a date.
* @return new instance of {@link IsoWeekYear}.
* @throws IllegalArgumentException if given value is {@literal null}.
* @since 2.1
*/
public static IsoWeekYear isoWeekYear(Object value) {
Assert.notNull(value, "value must not be null");
return new IsoWeekYear(value);
}
/**
* Creates new {@link IsoWeekYear}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link IsoWeekYear}.
*/
public static IsoWeekYear isoWeekYearOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return isoWeekYear(Fields.field(fieldReference));
}
/**
* Creates new {@link Millisecond}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link IsoWeekYear}.
*/
public static IsoWeekYear isoWeekYearOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return isoWeekYear(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link IsoWeekYear}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
* @since 2.1
*/
@Override
@Contract("_ -> new")
public IsoWeekYear withTimezone(Timezone timezone) {
Assert.notNull(timezone, "Timezone must not be null");
return new IsoWeekYear(appendTimezone(values().iterator().next(), timezone));
}
@Override
protected String getMongoMethod() {
return "$isoWeekYear";
}
}
/**
* @author Christoph Strobl
* @since 2.1
*/
public interface DateParts<T extends DateParts<T>> {
/**
* Set the {@literal hour} to the given value which must resolve to a value in range of {@code 0 - 23}. Can be a
* simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param hour must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal hour} is {@literal null}
*/
T hour(Object hour);
/**
* Set the {@literal hour} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
default T hourOf(String fieldReference) {
return hour(Fields.field(fieldReference));
}
/**
* Set the {@literal hour} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
default T hourOf(AggregationExpression expression) {
return hour(expression);
}
/**
* Set the {@literal minute} to the given value which must resolve to a value in range {@code 0 - 59}. Can be a
* simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param minute must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal minute} is {@literal null}
*/
T minute(Object minute);
/**
* Set the {@literal minute} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
default T minuteOf(String fieldReference) {
return minute(Fields.field(fieldReference));
}
/**
* Set the {@literal minute} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
default T minuteOf(AggregationExpression expression) {
return minute(expression);
}
/**
* Set the {@literal second} to the given value which must resolve to a value in range {@code 0 - 59}. Can be a
* simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param second must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal second} is {@literal null}
*/
T second(Object second);
/**
* Set the {@literal second} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
default T secondOf(String fieldReference) {
return second(Fields.field(fieldReference));
}
/**
* Set the {@literal second} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
default T secondOf(AggregationExpression expression) {
return second(expression);
}
/**
* Set the {@literal millisecond} to the given value which must resolve to a value in range {@code 0 - 999}. Can be
* a simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param millisecond must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal millisecond} is {@literal null}
* @since 3.2
*/
T millisecond(Object millisecond);
/**
* Set the {@literal millisecond} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
* @since 3.2
*/
default T millisecondOf(String fieldReference) {
return millisecond(Fields.field(fieldReference));
}
/**
* Set the {@literal milliseconds} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
* @since 3.2
*/
default T millisecondOf(AggregationExpression expression) {
return millisecond(expression);
}
}
/**
* {@link AggregationExpression} for {@code $dateFromParts}.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @author Matt Morrissette
* @author Christoph Strobl
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/</a>
* @since 2.1
*/
public static class DateFromParts extends TimezonedDateAggregationExpression implements DateParts<DateFromParts> {
private DateFromParts(Object value) {
super(value);
}
/**
* Creates new {@link DateFromPartsWithYear}.
*
* @return new instance of {@link DateFromPartsWithYear}.
* @since 2.1
*/
public static DateFromPartsWithYear dateFromParts() {
return year -> new DateFromParts(Collections.singletonMap("year", year));
}
/**
* Set the {@literal month} to the given value which must resolve to a calendar month in range {@code 1 - 12}. Can
* be a simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param month must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal month} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromParts month(Object month) {
return new DateFromParts(append("month", month));
}
/**
* Set the {@literal month} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromParts monthOf(String fieldReference) {
return month(Fields.field(fieldReference));
}
/**
* Set the {@literal month} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromParts monthOf(AggregationExpression expression) {
return month(expression);
}
/**
* Set the {@literal day} to the given value which must resolve to a calendar day in range {@code 1 - 31}. Can be a
* simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param day must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal day} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromParts day(Object day) {
return new DateFromParts(append("day", day));
}
/**
* Set the {@literal day} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromParts dayOf(String fieldReference) {
return day(Fields.field(fieldReference));
}
/**
* Set the {@literal day} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromParts dayOf(AggregationExpression expression) {
return day(expression);
}
@Override
@Contract("_ -> new")
public DateFromParts hour(Object hour) {
return new DateFromParts(append("hour", hour));
}
@Override
@Contract("_ -> new")
public DateFromParts minute(Object minute) {
return new DateFromParts(append("minute", minute));
}
@Override
@Contract("_ -> new")
public DateFromParts second(Object second) {
return new DateFromParts(append("second", second));
}
@Override
@Contract("_ -> new")
public DateFromParts millisecond(Object millisecond) {
return new DateFromParts(append("millisecond", millisecond));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateFromParts}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
*/
@Override
@Contract("_ -> new")
public DateFromParts withTimezone(Timezone timezone) {
return new DateFromParts(appendTimezone(argumentMap(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dateFromParts";
}
/**
* @author Christoph Strobl
*/
public interface DateFromPartsWithYear {
/**
* Set the {@literal year} to the given value which must resolve to a calendar year. Can be a simple value,
* {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param year must not be {@literal null}.
* @return new instance of {@link DateFromParts}.
* @throws IllegalArgumentException if given {@literal year} is {@literal null}
*/
DateFromParts year(Object year);
/**
* Set the {@literal year} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateFromParts}.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
default DateFromParts yearOf(String fieldReference) {
Assert.hasText(fieldReference, "Field reference must not be null nor empty");
return year(Fields.field(fieldReference));
}
/**
* Set the {@literal year} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateFromParts}.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
default DateFromParts yearOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return year(expression);
}
}
}
/**
* {@link AggregationExpression} for {@code $dateFromParts} using ISO week date.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @author Matt Morrissette
* @author Christoph Strobl
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/</a>
* @since 2.1
*/
public static class IsoDateFromParts extends TimezonedDateAggregationExpression
implements DateParts<IsoDateFromParts> {
private IsoDateFromParts(Object value) {
super(value);
}
/**
* Creates new {@link IsoDateFromPartsWithYear}.
*
* @return new instance of {@link IsoDateFromPartsWithYear}.
* @since 2.1
*/
public static IsoDateFromPartsWithYear dateFromParts() {
return year -> new IsoDateFromParts(Collections.singletonMap("isoWeekYear", year));
}
/**
* Set the {@literal week of year} to the given value which must resolve to a calendar week in range {@code 1 - 53}.
* Can be a simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param isoWeek must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal isoWeek} is {@literal null}.
*/
@Contract("_ -> new")
public IsoDateFromParts isoWeek(Object isoWeek) {
return new IsoDateFromParts(append("isoWeek", isoWeek));
}
/**
* Set the {@literal week of year} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
@Contract("_ -> new")
public IsoDateFromParts isoWeekOf(String fieldReference) {
return isoWeek(Fields.field(fieldReference));
}
/**
* Set the {@literal week of year} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
@Contract("_ -> new")
public IsoDateFromParts isoWeekOf(AggregationExpression expression) {
return isoWeek(expression);
}
/**
* Set the {@literal day of week} to the given value which must resolve to a weekday in range {@code 1 - 7}. Can be
* a simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param day must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal isoWeek} is {@literal null}.
*/
@Contract("_ -> new")
public IsoDateFromParts isoDayOfWeek(Object day) {
return new IsoDateFromParts(append("isoDayOfWeek", day));
}
/**
* Set the {@literal day of week} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
@Contract("_ -> new")
public IsoDateFromParts isoDayOfWeekOf(String fieldReference) {
return isoDayOfWeek(Fields.field(fieldReference));
}
/**
* Set the {@literal day of week} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
@Contract("_ -> new")
public IsoDateFromParts isoDayOfWeekOf(AggregationExpression expression) {
return isoDayOfWeek(expression);
}
@Override
@Contract("_ -> new")
public IsoDateFromParts hour(Object hour) {
return new IsoDateFromParts(append("hour", hour));
}
@Override
@Contract("_ -> new")
public IsoDateFromParts minute(Object minute) {
return new IsoDateFromParts(append("minute", minute));
}
@Override
@Contract("_ -> new")
public IsoDateFromParts second(Object second) {
return new IsoDateFromParts(append("second", second));
}
@Override
@Contract("_ -> new")
public IsoDateFromParts millisecond(Object millisecond) {
return new IsoDateFromParts(append("millisecond", millisecond));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link IsoDateFromParts}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
*/
@Override
@Contract("_ -> new")
public IsoDateFromParts withTimezone(Timezone timezone) {
return new IsoDateFromParts(appendTimezone(argumentMap(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dateFromParts";
}
/**
* @author Christoph Strobl
*/
public interface IsoDateFromPartsWithYear {
/**
* Set the {@literal week date year} to the given value which must resolve to a weekday in range {@code 0 - 9999}.
* Can be a simple value, {@link Field field reference} or {@link AggregationExpression expression}.
*
* @param isoWeekYear must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal isoWeekYear} is {@literal null}.
*/
IsoDateFromParts isoWeekYear(Object isoWeekYear);
/**
* Set the {@literal week date year} to the value resolved by following the given {@link Field field reference}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
default IsoDateFromParts isoWeekYearOf(String fieldReference) {
Assert.hasText(fieldReference, "Field reference must not be null nor empty");
return isoWeekYear(Fields.field(fieldReference));
}
/**
* Set the {@literal week date year} to the result of the given {@link AggregationExpression expression}.
*
* @param expression must not be {@literal null}.
* @return new instance.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
default IsoDateFromParts isoWeekYearOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return isoWeekYear(expression);
}
}
}
/**
* {@link AggregationExpression} for {@code $dateToParts}.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @author Matt Morrissette
* @author Christoph Strobl
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/dateToParts/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateToParts/</a>
* @since 2.1
*/
public static class DateToParts extends TimezonedDateAggregationExpression {
private DateToParts(Object value) {
super(value);
}
/**
* Creates new {@link DateToParts}.
*
* @param value must not be {@literal null}.
* @return new instance of {@link DateToParts}.
* @throws IllegalArgumentException if given {@literal value} is {@literal null}.
*/
public static DateToParts dateToParts(Object value) {
Assert.notNull(value, "Value must not be null");
return new DateToParts(Collections.singletonMap("date", value));
}
/**
* Creates new {@link DateToParts}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateToParts}.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
public static DateToParts datePartsOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return dateToParts(Fields.field(fieldReference));
}
/**
* Creates new {@link DateToParts}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateToParts}.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
public static DateToParts datePartsOf(AggregationExpression expression) {
return dateToParts(expression);
}
/**
* Use ISO week date fields in the resulting document.
*
* @return new instance of {@link DateToParts}.
*/
@Contract("-> new")
public DateToParts iso8601() {
return new DateToParts(append("iso8601", true));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateFromParts}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
*/
@Override
@Contract("_ -> new")
public DateToParts withTimezone(Timezone timezone) {
return new DateToParts(appendTimezone(argumentMap(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dateToParts";
}
}
/**
* {@link AggregationExpression} for {@code $dateFromString}.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @author Matt Morrissette
* @author Christoph Strobl
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/</a>
* @since 2.1
*/
public static class DateFromString extends TimezonedDateAggregationExpression {
private DateFromString(Object value) {
super(value);
}
/**
* Creates new {@link DateFromString}.
*
* @param value must not be {@literal null}.
* @return new instance of {@link DateFromString}.
* @throws IllegalArgumentException if given {@literal value} is {@literal null}.
*/
public static DateFromString fromString(Object value) {
return new DateFromString(Collections.singletonMap("dateString", value));
}
/**
* Creates new {@link DateFromString}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateFromString}.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
@Contract("_ -> new")
public static DateFromString fromStringOf(String fieldReference) {
return fromString(Fields.field(fieldReference));
}
/**
* Creates new {@link DateFromString}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateFromString}.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
@Contract("_ -> new")
public static DateFromString fromStringOf(AggregationExpression expression) {
return fromString(expression);
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 3.6 or later.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateFromString}.
* @throws IllegalArgumentException if given {@literal timezone} is {@literal null}.
*/
@Override
@Contract("_ -> new")
public DateFromString withTimezone(Timezone timezone) {
return new DateFromString(appendTimezone(argumentMap(), timezone));
}
/**
* Optionally set the date format to use. If not specified {@code %Y-%m-%dT%H:%M:%S.%LZ} is used.<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param format must not be {@literal null}.
* @return new instance of {@link DateFromString}.
* @throws IllegalArgumentException if given {@literal format} is {@literal null}.
*/
@Contract("_ -> new")
public DateFromString withFormat(String format) {
Assert.notNull(format, "Format must not be null");
return new DateFromString(append("format", format));
}
@Override
protected String getMongoMethod() {
return "$dateFromString";
}
}
/**
* {@link AggregationExpression} for {@code $dateAdd}.<br />
* <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
*
* @author Christoph Strobl
* @since 3.3
*/
public static class DateAdd extends TimezonedDateAggregationExpression {
private DateAdd(Object value) {
super(value);
}
/**
* Add the number of {@literal units} of the result of the given {@link AggregationExpression expression} to a
* {@link #toDate(Object) start date}.
*
* @param expression must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
public static DateAdd addValueOf(AggregationExpression expression, String unit) {
return addValue(expression, unit);
}
/**
* Add the number of {@literal units} from a {@literal field} to a {@link #toDate(Object) start date}.
*
* @param fieldReference must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
public static DateAdd addValueOf(String fieldReference, String unit) {
return addValue(Fields.field(fieldReference), unit);
}
/**
* Add the number of {@literal units} to a {@link #toDate(Object) start date}.
*
* @param value must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
public static DateAdd addValue(Object value, String unit) {
Map<String, Object> args = new HashMap<>();
args.put("unit", unit);
args.put("amount", value);
return new DateAdd(args);
}
/**
* Define the start date, in UTC, for the addition operation.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateAdd toDateOf(AggregationExpression expression) {
return toDate(expression);
}
/**
* Define the start date, in UTC, for the addition operation.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateAdd toDateOf(String fieldReference) {
return toDate(Fields.field(fieldReference));
}
/**
* Define the start date, in UTC, for the addition operation.
*
* @param dateExpression anything that evaluates to a valid date. Must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateAdd toDate(Object dateExpression) {
return new DateAdd(append("startDate", dateExpression));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateAdd withTimezone(Timezone timezone) {
return new DateAdd(appendTimezone(argumentMap(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dateAdd";
}
}
/**
* {@link AggregationExpression} for {@code $dateSubtract}.<br />
* <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
*
* @author Christoph Strobl
* @since 4.0
*/
public static class DateSubtract extends TimezonedDateAggregationExpression {
private DateSubtract(Object value) {
super(value);
}
/**
* Subtract the number of {@literal units} of the result of the given {@link AggregationExpression expression} from
* a {@link #fromDate(Object) start date}.
*
* @param expression must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
*/
public static DateSubtract subtractValueOf(AggregationExpression expression, String unit) {
return subtractValue(expression, unit);
}
/**
* Subtract the number of {@literal units} from a {@literal field} from a {@link #fromDate(Object) start date}.
*
* @param fieldReference must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
*/
public static DateSubtract subtractValueOf(String fieldReference, String unit) {
return subtractValue(Fields.field(fieldReference), unit);
}
/**
* Subtract the number of {@literal units} from a {@link #fromDate(Object) start date}.
*
* @param value must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
*/
public static DateSubtract subtractValue(Object value, String unit) {
Map<String, Object> args = new HashMap<>();
args.put("unit", unit);
args.put("amount", value);
return new DateSubtract(args);
}
/**
* Define the start date, in UTC, for the subtraction operation.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
*/
@Contract("_ -> new")
public DateSubtract fromDateOf(AggregationExpression expression) {
return fromDate(expression);
}
/**
* Define the start date, in UTC, for the subtraction operation.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
*/
@Contract("_ -> new")
public DateSubtract fromDateOf(String fieldReference) {
return fromDate(Fields.field(fieldReference));
}
/**
* Define the start date, in UTC, for the subtraction operation.
*
* @param dateExpression anything that evaluates to a valid date. Must not be {@literal null}.
* @return new instance of {@link DateSubtract}.
*/
@Contract("_ -> new")
public DateSubtract fromDate(Object dateExpression) {
return new DateSubtract(append("startDate", dateExpression));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateSubtract}.
*/
@Contract("_ -> new")
public DateSubtract withTimezone(Timezone timezone) {
return new DateSubtract(appendTimezone(argumentMap(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dateSubtract";
}
}
/**
* {@link AggregationExpression} for {@code $dateDiff}.<br />
* <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
*
* @author Christoph Strobl
* @since 3.3
*/
public static class DateDiff extends TimezonedDateAggregationExpression {
private DateDiff(Object value) {
super(value);
}
/**
* Add the number of {@literal units} of the result of the given {@link AggregationExpression expression} to a
* {@link #toDate(Object) start date}.
*
* @param expression must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
public static DateDiff diffValueOf(AggregationExpression expression, String unit) {
return diffValue(expression, unit);
}
/**
* Add the number of {@literal units} from a {@literal field} to a {@link #toDate(Object) start date}.
*
* @param fieldReference must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
public static DateDiff diffValueOf(String fieldReference, String unit) {
return diffValue(Fields.field(fieldReference), unit);
}
/**
* Add the number of {@literal units} to a {@link #toDate(Object) start date}.
*
* @param value must not be {@literal null}.
* @param unit must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
public static DateDiff diffValue(Object value, String unit) {
Map<String, Object> args = new HashMap<>();
args.put("unit", unit);
args.put("endDate", value);
return new DateDiff(args);
}
/**
* Define the start date, in UTC, for the addition operation.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateDiff toDateOf(AggregationExpression expression) {
return toDate(expression);
}
/**
* Define the start date, in UTC, for the addition operation.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateDiff toDateOf(String fieldReference) {
return toDate(Fields.field(fieldReference));
}
/**
* Define the start date, in UTC, for the addition operation.
*
* @param dateExpression anything that evaluates to a valid date. Must not be {@literal null}.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateDiff toDate(Object dateExpression) {
return new DateDiff(append("startDate", dateExpression));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateAdd}.
*/
@Contract("_ -> new")
public DateDiff withTimezone(Timezone timezone) {
return new DateDiff(appendTimezone(argumentMap(), timezone));
}
/**
* Set the start day of the week if the unit if measure is set to {@literal week}. Uses {@literal Sunday} by
* default.
*
* @param day must not be {@literal null}.
* @return new instance of {@link DateDiff}.
*/
@Contract("_ -> new")
public DateDiff startOfWeek(Object day) {
return new DateDiff(append("startOfWeek", day));
}
@Override
protected String getMongoMethod() {
return "$dateDiff";
}
}
/**
* {@link AggregationExpression} for {@code $dateTrunc}.<br />
* <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
*
* @author Christoph Strobl
* @since 4.0
*/
public static class DateTrunc extends TimezonedDateAggregationExpression {
private DateTrunc(Object value) {
super(value);
}
/**
* Truncates the date value of computed by the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
public static DateTrunc truncateValueOf(AggregationExpression expression) {
return truncateValue(expression);
}
/**
* Truncates the date value of the referenced {@literal field}.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
public static DateTrunc truncateValueOf(String fieldReference) {
return truncateValue(Fields.field(fieldReference));
}
/**
* Truncates the date value.
*
* @param value must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
public static DateTrunc truncateValue(Object value) {
return new DateTrunc(Collections.singletonMap("date", value));
}
/**
* Define the unit of time.
*
* @param unit must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc to(String unit) {
return new DateTrunc(append("unit", unit));
}
/**
* Define the unit of time via an {@link AggregationExpression}.
*
* @param unit must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc to(AggregationExpression unit) {
return new DateTrunc(append("unit", unit));
}
/**
* Define the weeks starting day if {@link #to(String)} resolves to {@literal week}.
*
* @param day must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc startOfWeek(java.time.DayOfWeek day) {
return startOfWeek(day.name().toLowerCase(Locale.US));
}
/**
* Define the weeks starting day if {@link #to(String)} resolves to {@literal week}.
*
* @param day must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc startOfWeek(String day) {
return new DateTrunc(append("startOfWeek", day));
}
/**
* Define the numeric time value.
*
* @param binSize must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc binSize(int binSize) {
return binSize((Object) binSize);
}
/**
* Define the numeric time value via an {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc binSize(AggregationExpression expression) {
return binSize((Object) expression);
}
/**
* Define the numeric time value.
*
* @param binSize must not be {@literal null}.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc binSize(Object binSize) {
return new DateTrunc(append("binSize", binSize));
}
/**
* Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.
*
* @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
* @return new instance of {@link DateTrunc}.
*/
@Contract("_ -> new")
public DateTrunc withTimezone(Timezone timezone) {
return new DateTrunc(appendTimezone(argumentMap(), timezone));
}
@Override
protected String getMongoMethod() {
return "$dateTrunc";
}
}
/**
* {@link AggregationExpression} for {@code $tsIncrement}.
*
* @author Christoph Strobl
* @since 4.0
*/
public static class TsIncrement extends AbstractAggregationExpression {
private TsIncrement(Object value) {
super(value);
}
/**
* Creates new {@link TsIncrement} that returns the incrementing ordinal from a timestamp.
*
* @param value must not be {@literal null}.
* @return new instance of {@link TsIncrement}.
* @throws IllegalArgumentException if given {@literal value} is {@literal null}.
*/
public static TsIncrement tsIncrement(Object value) {
Assert.notNull(value, "Value must not be null");
return new TsIncrement(value);
}
/**
* Creates new {@link TsIncrement} that returns the incrementing ordinal from a timestamp.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link TsIncrement}.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
public static TsIncrement tsIncrementValueOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return tsIncrement(Fields.field(fieldReference));
}
/**
* Creates new {@link TsIncrement}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link TsIncrement}.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
public static TsIncrement tsIncrementValueOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return tsIncrement(expression);
}
@Override
protected String getMongoMethod() {
return "$tsIncrement";
}
}
/**
* {@link AggregationExpression} for {@code $tsSecond}.
*
* @author Christoph Strobl
* @since 4.0
*/
public static class TsSecond extends AbstractAggregationExpression {
private TsSecond(Object value) {
super(value);
}
/**
* Creates new {@link TsSecond} that returns the incrementing ordinal from a timestamp.
*
* @param value must not be {@literal null}.
* @return new instance of {@link TsSecond}.
* @throws IllegalArgumentException if given {@literal value} is {@literal null}.
*/
public static TsSecond tsSecond(Object value) {
Assert.notNull(value, "Value must not be null");
return new TsSecond(value);
}
/**
* Creates new {@link TsSecond} that returns the incrementing ordinal from a timestamp.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link TsSecond}.
* @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}.
*/
public static TsSecond tsSecondValueOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null");
return tsSecond(Fields.field(fieldReference));
}
/**
* Creates new {@link TsSecond}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link TsSecond}.
* @throws IllegalArgumentException if given {@literal expression} is {@literal null}.
*/
public static TsSecond tsSecondValueOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null");
return tsSecond(expression);
}
@Override
protected String getMongoMethod() {
return "$tsSecond";
}
}
/**
* Interface defining a temporal unit for date operators.
*
* @author Mark Paluch
* @since 3.3
*/
public interface TemporalUnit {
String name();
/**
* Converts the given time unit into a {@link TemporalUnit}. Supported units are: days, hours, minutes, seconds, and
* milliseconds.
*
* @param timeUnit the time unit to convert, must not be {@literal null}.
* @return
* @throws IllegalArgumentException if the {@link TimeUnit} is {@literal null} or not supported for conversion.
*/
static TemporalUnit from(TimeUnit timeUnit) {
Assert.notNull(timeUnit, "TimeUnit must not be null");
switch (timeUnit) {
case DAYS:
return TemporalUnits.DAY;
case HOURS:
return TemporalUnits.HOUR;
case MINUTES:
return TemporalUnits.MINUTE;
case SECONDS:
return TemporalUnits.SECOND;
case MILLISECONDS:
return TemporalUnits.MILLISECOND;
}
throw new IllegalArgumentException(String.format("Cannot create TemporalUnit from %s", timeUnit));
}
/**
* Converts the given chrono unit into a {@link TemporalUnit}. Supported units are: years, weeks, months, days,
* hours, minutes, seconds, and millis.
*
* @param chronoUnit the chrono unit to convert, must not be {@literal null}.
* @return
* @throws IllegalArgumentException if the {@link TimeUnit} is {@literal null} or not supported for conversion.
*/
static TemporalUnit from(ChronoUnit chronoUnit) {
switch (chronoUnit) {
case YEARS:
return TemporalUnits.YEAR;
case WEEKS:
return TemporalUnits.WEEK;
case MONTHS:
return TemporalUnits.MONTH;
case DAYS:
return TemporalUnits.DAY;
case HOURS:
return TemporalUnits.HOUR;
case MINUTES:
return TemporalUnits.MINUTE;
case SECONDS:
return TemporalUnits.SECOND;
case MILLIS:
return TemporalUnits.MILLISECOND;
}
throw new IllegalArgumentException(String.format("Cannot create TemporalUnit from %s", chronoUnit));
}
}
/**
* Supported temporal units.
*/
enum TemporalUnits implements TemporalUnit {
YEAR, QUARTER, WEEK, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND
}
@SuppressWarnings("unchecked")
private static <T extends TimezonedDateAggregationExpression> T applyTimezone(T instance, Timezone timezone) {
return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone()
? (T) instance.withTimezone(timezone)
: instance;
}
}