diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java
index a97d64c52..029b994f2 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java
@@ -15,10 +15,16 @@
*/
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.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -157,6 +163,7 @@ public class DateOperators {
* NOTE: Support for timezones in aggregations Requires MongoDB 3.6 or later.
*
* @author Christoph Strobl
+ * @author Mark Paluch
* @since 2.1
*/
public static class Timezone {
@@ -192,6 +199,61 @@ public class DateOperators {
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.
*
@@ -212,6 +274,11 @@ public class DateOperators {
public static Timezone ofExpression(AggregationExpression expression) {
return valueOf(expression);
}
+
+ @Nullable
+ Object getValue() {
+ return value;
+ }
}
/**
@@ -303,32 +370,64 @@ public class DateOperators {
/**
* Creates new {@link AggregationExpression} that adds the value of the given {@link AggregationExpression
- * expression} (in {@literal units). @param expression must not be {@literal null}.
- *
+ * 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
+ * @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 stored at the given {@literal field} (in
- * {@literal units). @param fieldReference must not be {@literal null}.
- *
+ * 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
+ * @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 given value (in {@literal units). @param value must not
- * be {@literal null}. @param unit the unit of measure. Must not be {@literal null}.
- *
+ * 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}.
*/
@@ -336,6 +435,22 @@ public class DateOperators {
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 returns the day of the year for a date as a number between 1 and
* 366.
@@ -367,41 +482,89 @@ public class DateOperators {
}
/**
- * 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}.
- *
+ * 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
+ * @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 stored
- * at the given {@literal field}. @param expression must not be {@literal null}.
- *
+ * 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
+ * @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 given
- * {@literal value}. @param value anything the resolves to a valid date. Must not be {@literal null}.
- *
+ * 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
+ * @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.
*
@@ -2720,6 +2883,85 @@ public class DateOperators {
}
}
+ /**
+ * 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 applyTimezone(T instance, Timezone timezone) {
return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone()
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java
index 9c40a0b64..fa01b02b9 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java
@@ -15,9 +15,11 @@
*/
package org.springframework.data.mongodb.core.aggregation;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import org.bson.Document;
import org.springframework.data.domain.Sort;
@@ -626,7 +628,68 @@ public class SetWindowFieldsOperation
* The actual time unit to apply to a {@link Window}.
*/
public interface WindowUnit {
+
String name();
+
+ /**
+ * Converts the given time unit into a {@link WindowUnit}. 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 WindowUnit from(TimeUnit timeUnit) {
+
+ Assert.notNull(timeUnit, "TimeUnit must not be null");
+
+ switch (timeUnit) {
+ case DAYS:
+ return WindowUnits.DAY;
+ case HOURS:
+ return WindowUnits.HOUR;
+ case MINUTES:
+ return WindowUnits.MINUTE;
+ case SECONDS:
+ return WindowUnits.SECOND;
+ case MILLISECONDS:
+ return WindowUnits.MILLISECOND;
+ }
+
+ throw new IllegalArgumentException(String.format("Cannot create WindowUnit from %s", timeUnit));
+ }
+
+ /**
+ * Converts the given chrono unit into a {@link WindowUnit}. 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 WindowUnit from(ChronoUnit chronoUnit) {
+
+ switch (chronoUnit) {
+ case YEARS:
+ return WindowUnits.YEAR;
+ case WEEKS:
+ return WindowUnits.WEEK;
+ case MONTHS:
+ return WindowUnits.MONTH;
+ case DAYS:
+ return WindowUnits.DAY;
+ case HOURS:
+ return WindowUnits.HOUR;
+ case MINUTES:
+ return WindowUnits.MINUTE;
+ case SECONDS:
+ return WindowUnits.SECOND;
+ case MILLIS:
+ return WindowUnits.MILLISECOND;
+ }
+
+ throw new IllegalArgumentException(String.format("Cannot create WindowUnit from %s", chronoUnit));
+ }
}
/**
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java
index 95f977ed7..6d63b954f 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java
@@ -15,14 +15,22 @@
*/
package org.springframework.data.mongodb.core.aggregation;
-import static org.assertj.core.api.Assertions.*;
+import static org.springframework.data.mongodb.test.util.Assertions.*;
+
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoUnit;
+import java.util.TimeZone;
-import org.bson.Document;
import org.junit.jupiter.api.Test;
+
import org.springframework.data.mongodb.core.aggregation.DateOperators.Timezone;
/**
+ * Unit tests for {@link DateOperators}.
+ *
* @author Christoph Strobl
+ * @author Mark Paluch
*/
class DateOperatorsUnitTests {
@@ -30,15 +38,15 @@ class DateOperatorsUnitTests {
void rendersDateAdd() {
assertThat(DateOperators.dateOf("purchaseDate").add(3, "day").toDocument(Aggregation.DEFAULT_CONTEXT))
- .isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }"));
+ .isEqualTo("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }");
}
@Test // GH-3713
void rendersDateAddWithTimezone() {
assertThat(DateOperators.zonedDateOf("purchaseDate", Timezone.valueOf("America/Chicago")).add(3, "day")
- .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse(
- "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }"));
+ .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(
+ "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }");
}
@Test // GH-3713
@@ -46,15 +54,37 @@ class DateOperatorsUnitTests {
assertThat(
DateOperators.dateOf("purchaseDate").diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT))
- .isEqualTo(Document
- .parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }"));
+ .isEqualTo("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }");
}
@Test // GH-3713
void rendersDateDiffWithTimezone() {
assertThat(DateOperators.zonedDateOf("purchaseDate", Timezone.valueOf("America/Chicago"))
- .diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse(
- "{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\", timezone : \"America/Chicago\" } }"));
+ .diffValueOf("delivered", DateOperators.TemporalUnit.from(ChronoUnit.DAYS))
+ .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(
+ "{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\", timezone : \"America/Chicago\" } }");
+ }
+
+ @Test // GH-3713
+ void rendersTimezoneFromZoneOffset() {
+ assertThat(DateOperators.Timezone.fromOffset(ZoneOffset.ofHoursMinutes(3, 30)).getValue()).isEqualTo("+03:30");
+ }
+
+ @Test // GH-3713
+ void rendersTimezoneFromTimeZoneOffset() {
+ assertThat(DateOperators.Timezone.fromOffset(TimeZone.getTimeZone("America/Chicago")).getValue())
+ .isEqualTo("-06:00");
+ }
+
+ @Test // GH-3713
+ void rendersTimezoneFromTimeZoneId() {
+ assertThat(DateOperators.Timezone.fromZone(TimeZone.getTimeZone("America/Chicago")).getValue())
+ .isEqualTo("America/Chicago");
+ }
+
+ @Test // GH-3713
+ void rendersTimezoneFromZoneId() {
+ assertThat(DateOperators.Timezone.fromZone(ZoneId.of("America/Chicago")).getValue()).isEqualTo("America/Chicago");
}
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java
index 33edab1d5..bc8da0a3c 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java
@@ -1034,11 +1034,6 @@ public class SpelExpressionTransformerUnitTests {
assertThat(transform("tanh(angle)")).isEqualTo("{ \"$tanh\" : \"$angle\"}");
}
- private Document transform(String expression, Object... params) {
- return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
- }
-
- private Object transformValue(String expression, Object... params) {
@Test // GH-3713
void shouldRenderDateAdd() {
assertThat(transform("dateAdd(purchaseDate, 'day', 3)")).isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }"));
@@ -1049,7 +1044,11 @@ public class SpelExpressionTransformerUnitTests {
assertThat(transform("dateDiff(purchaseDate, delivered, 'day')")).isEqualTo(Document.parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }"));
}
- private Object transform(String expression, Object... params) {
+ private Document transform(String expression, Object... params) {
+ return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
+ }
+
+ private Object transformValue(String expression, Object... params) {
Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result);
}
diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc
index f23b29069..bc7a032e7 100644
--- a/src/main/asciidoc/reference/aggregation-framework.adoc
+++ b/src/main/asciidoc/reference/aggregation-framework.adoc
@@ -100,7 +100,7 @@ At the time of this writing, we provide support for the following Aggregation Op
| `literal`
| Date Aggregation Operators
-| `dayOfYear`, `dayOfMonth`, `dayOfWeek`, `year`, `month`, `week`, `hour`, `minute`, `second`, `millisecond`, `dateToString`, `dateFromString`, `dateFromParts`, `dateToParts`, `isoDayOfWeek`, `isoWeek`, `isoWeekYear`
+| `dayOfYear`, `dayOfMonth`, `dayOfWeek`, `year`, `month`, `week`, `hour`, `minute`, `second`, `millisecond`, `dateAdd`, `dateDiff`, `dateToString`, `dateFromString`, `dateFromParts`, `dateToParts`, `isoDayOfWeek`, `isoWeek`, `isoWeekYear`
| Variable Operators
| `map`