@@ -449,6 +449,95 @@ public DateAdd add(Object value, TemporalUnit unit) {
449449 timezone );
450450 }
451451
452+ /**
453+ * Creates new {@link AggregationExpression} that subtracts the value of the given {@link AggregationExpression
454+ * expression} (in {@literal units}).
455+ *
456+ * @param expression must not be {@literal null}.
457+ * @param unit the unit of measure. Must not be {@literal null}.
458+ * @return new instance of {@link DateSubtract}.
459+ * @since 4.0
460+ */
461+ public DateSubtract subtractValueOf (AggregationExpression expression , String unit ) {
462+ return applyTimezone (DateSubtract .subtractValueOf (expression , unit ).fromDate (dateReference ()), timezone );
463+ }
464+
465+ /**
466+ * Creates new {@link AggregationExpression} that subtracts the value of the given {@link AggregationExpression
467+ * expression} (in {@literal units}).
468+ *
469+ * @param expression must not be {@literal null}.
470+ * @param unit the unit of measure. Must not be {@literal null}.
471+ * @return new instance of {@link DateSubtract}.
472+ * @since 4.0
473+ */
474+ public DateSubtract subtractValueOf (AggregationExpression expression , TemporalUnit unit ) {
475+
476+ Assert .notNull (unit , "TemporalUnit must not be null" );
477+ return applyTimezone (
478+ DateSubtract .subtractValueOf (expression , unit .name ().toLowerCase (Locale .ROOT )).fromDate (dateReference ()),
479+ timezone );
480+ }
481+
482+ /**
483+ * Creates new {@link AggregationExpression} that subtracts the value stored at the given {@literal field} (in
484+ * {@literal units}).
485+ *
486+ * @param fieldReference must not be {@literal null}.
487+ * @param unit the unit of measure. Must not be {@literal null}.
488+ * @return new instance of {@link DateSubtract}.
489+ * @since 4.0
490+ */
491+ public DateSubtract subtractValueOf (String fieldReference , String unit ) {
492+ return applyTimezone (DateSubtract .subtractValueOf (fieldReference , unit ).fromDate (dateReference ()), timezone );
493+ }
494+
495+ /**
496+ * Creates new {@link AggregationExpression} that subtracts the value stored at the given {@literal field} (in
497+ * {@literal units}).
498+ *
499+ * @param fieldReference must not be {@literal null}.
500+ * @param unit the unit of measure. Must not be {@literal null}.
501+ * @return new instance of {@link DateSubtract}.
502+ * @since 4.0
503+ */
504+ public DateSubtract subtractValueOf (String fieldReference , TemporalUnit unit ) {
505+
506+ Assert .notNull (unit , "TemporalUnit must not be null" );
507+
508+ return applyTimezone (
509+ DateSubtract .subtractValueOf (fieldReference , unit .name ().toLowerCase (Locale .ROOT )).fromDate (dateReference ()),
510+ timezone );
511+ }
512+
513+ /**
514+ * Creates new {@link AggregationExpression} that subtracts the given value (in {@literal units}).
515+ *
516+ * @param value must not be {@literal null}.
517+ * @param unit the unit of measure. Must not be {@literal null}.
518+ * @return new instance of {@link DateSubtract}.
519+ * @since 4.0
520+ */
521+ public DateSubtract subtract (Object value , String unit ) {
522+ return applyTimezone (DateSubtract .subtractValue (value , unit ).fromDate (dateReference ()), timezone );
523+ }
524+
525+ /**
526+ * Creates new {@link AggregationExpression} that subtracts the given value (in {@literal units}).
527+ *
528+ * @param value must not be {@literal null}.
529+ * @param unit the unit of measure. Must not be {@literal null}.
530+ * @return new instance of {@link DateSubtract}.
531+ * @since 4.0
532+ */
533+ public DateSubtract subtract (Object value , TemporalUnit unit ) {
534+
535+ Assert .notNull (unit , "TemporalUnit must not be null" );
536+
537+ return applyTimezone (
538+ DateSubtract .subtractValue (value , unit .name ().toLowerCase (Locale .ROOT )).fromDate (dateReference ()), timezone );
539+ }
540+
452541 /**
453542 * Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and
454543 * 366.
@@ -2733,6 +2822,103 @@ protected String getMongoMethod() {
27332822 }
27342823 }
27352824
2825+ /**
2826+ * {@link AggregationExpression} for {@code $dateSubtract}.<br />
2827+ * <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
2828+ *
2829+ * @author Christoph Strobl
2830+ * @since 4.0
2831+ */
2832+ public static class DateSubtract extends TimezonedDateAggregationExpression {
2833+
2834+ private DateSubtract (Object value ) {
2835+ super (value );
2836+ }
2837+
2838+ /**
2839+ * Subtract the number of {@literal units} of the result of the given {@link AggregationExpression expression} from
2840+ * a {@link #fromDate(Object) start date}.
2841+ *
2842+ * @param expression must not be {@literal null}.
2843+ * @param unit must not be {@literal null}.
2844+ * @return new instance of {@link DateSubtract}.
2845+ */
2846+ public static DateSubtract subtractValueOf (AggregationExpression expression , String unit ) {
2847+ return subtractValue (expression , unit );
2848+ }
2849+
2850+ /**
2851+ * Subtract the number of {@literal units} from a {@literal field} from a {@link #fromDate(Object) start date}.
2852+ *
2853+ * @param fieldReference must not be {@literal null}.
2854+ * @param unit must not be {@literal null}.
2855+ * @return new instance of {@link DateSubtract}.
2856+ */
2857+ public static DateSubtract subtractValueOf (String fieldReference , String unit ) {
2858+ return subtractValue (Fields .field (fieldReference ), unit );
2859+ }
2860+
2861+ /**
2862+ * Subtract the number of {@literal units} from a {@link #fromDate(Object) start date}.
2863+ *
2864+ * @param value must not be {@literal null}.
2865+ * @param unit must not be {@literal null}.
2866+ * @return new instance of {@link DateSubtract}.
2867+ */
2868+ public static DateSubtract subtractValue (Object value , String unit ) {
2869+
2870+ Map <String , Object > args = new HashMap <>();
2871+ args .put ("unit" , unit );
2872+ args .put ("amount" , value );
2873+ return new DateSubtract (args );
2874+ }
2875+
2876+ /**
2877+ * Define the start date, in UTC, for the subtraction operation.
2878+ *
2879+ * @param expression must not be {@literal null}.
2880+ * @return new instance of {@link DateSubtract}.
2881+ */
2882+ public DateSubtract fromDateOf (AggregationExpression expression ) {
2883+ return fromDate (expression );
2884+ }
2885+
2886+ /**
2887+ * Define the start date, in UTC, for the subtraction operation.
2888+ *
2889+ * @param fieldReference must not be {@literal null}.
2890+ * @return new instance of {@link DateSubtract}.
2891+ */
2892+ public DateSubtract fromDateOf (String fieldReference ) {
2893+ return fromDate (Fields .field (fieldReference ));
2894+ }
2895+
2896+ /**
2897+ * Define the start date, in UTC, for the subtraction operation.
2898+ *
2899+ * @param dateExpression anything that evaluates to a valid date. Must not be {@literal null}.
2900+ * @return new instance of {@link DateSubtract}.
2901+ */
2902+ public DateSubtract fromDate (Object dateExpression ) {
2903+ return new DateSubtract (append ("startDate" , dateExpression ));
2904+ }
2905+
2906+ /**
2907+ * Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.
2908+ *
2909+ * @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
2910+ * @return new instance of {@link DateSubtract}.
2911+ */
2912+ public DateSubtract withTimezone (Timezone timezone ) {
2913+ return new DateSubtract (appendTimezone (argumentMap (), timezone ));
2914+ }
2915+
2916+ @ Override
2917+ protected String getMongoMethod () {
2918+ return "$dateSubtract" ;
2919+ }
2920+ }
2921+
27362922 /**
27372923 * {@link AggregationExpression} for {@code $dateDiff}.<br />
27382924 * <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
0 commit comments