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 3afee36e9..a76623ad8 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 @@ -1401,7 +1401,7 @@ public class DateOperators { public DateToString withTimezone(Timezone timezone) { Assert.notNull(timezone, "Timezone must not be null."); - return new DateToString(argumentMap(get("date"), (String) get("format"), timezone)); + return new DateToString(append("timezone", timezone)); } /** @@ -1461,6 +1461,25 @@ public class DateOperators { return args; } + protected java.util.Map append(String key, Object value) { + + java.util.Map clone = new LinkedHashMap(argumentMap()); + + if (value instanceof Timezone) { + + if (ObjectUtils.nullSafeEquals(value, Timezone.none())) { + clone.remove("timezone"); + } else { + clone.put("timezone", ((Timezone) value).value); + } + + } else { + clone.put(key, value); + } + + return clone; + } + public interface FormatBuilder { /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index 4385dd533..23e8f722e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -1213,7 +1213,7 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation { /** * Generates a {@code $dateToString} expression that takes the date representation of the previously mentioned field * using the server default format.
- * strong>NOTE: Requires MongoDB 4.0 or later. + * NOTE: Requires MongoDB 4.0 or later. * * @return * @since 1.10.15 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index 5084f0ae8..0e9f0013b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -1301,7 +1301,7 @@ public class ProjectionOperationUnitTests { is(JSON.parse("{ $project: { time: { $dateToString: { format: \"%H:%M:%S:%L\", date: \"$date\" } } } }"))); } - @Test // DATAMONGO-1834 + @Test // DATAMONGO-1834, DATAMONGO-2047 public void shouldRenderDateToStringAggregationExpressionWithTimezone() { DBObject agg = project() @@ -1310,6 +1310,13 @@ public class ProjectionOperationUnitTests { assertThat(agg, is(JSON.parse( "{ $project: { time: { $dateToString: { format: \"%H:%M:%S:%L\", date: \"$date\", \"timezone\" : \"America/Chicago\" } } } } } }"))); + + DBObject removedTimezone = project().and(DateOperators.dateOf("date") + .withTimezone(Timezone.valueOf("America/Chicago")).toString("%H:%M:%S:%L").withTimezone(Timezone.none())) + .as("time").toDBObject(Aggregation.DEFAULT_CONTEXT); + + assertThat(removedTimezone, + is(JSON.parse("{ $project: { time: { $dateToString: { format: \"%H:%M:%S:%L\", date: \"$date\" } } } } } }"))); } @Test // DATAMONGO-2047 @@ -1323,6 +1330,29 @@ public class ProjectionOperationUnitTests { .parse("{ $project: { time: { $dateToString: { date: \"$date\", \"onNull\" : \"$fallback-field\" } } } }"))); } + @Test // DATAMONGO-2047 + public void shouldRenderDateToStringWithOnNullExpression() { + + DBObject agg = project() + .and(DateOperators.dateOf("date").toStringWithDefaultFormat() + .onNullReturnValueOf(LiteralOperators.valueOf("my-literal").asLiteral())) + .as("time").toDBObject(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg, is(JSON.parse( + "{ $project: { time: { $dateToString: { date: \"$date\", \"onNull\" : { \"$literal\": \"my-literal\"} } } } }"))); + } + + @Test // DATAMONGO-2047 + public void shouldRenderDateToStringWithOnNullAndTimezone() { + + DBObject agg = project().and(DateOperators.dateOf("date").toStringWithDefaultFormat() + .onNullReturnValueOf("fallback-field").withTimezone(Timezone.ofField("foo"))).as("time") + .toDBObject(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg, is(JSON.parse( + "{ $project: { time: { $dateToString: { date: \"$date\", \"onNull\" : \"$fallback-field\", \"timezone\": \"$foo\" } } } }"))); + } + @Test // DATAMONGO-1536 public void shouldRenderSumAggregationExpression() {