@@ -538,6 +538,32 @@ public DateSubtract subtract(Object value, TemporalUnit unit) {
538538 DateSubtract .subtractValue (value , unit .name ().toLowerCase (Locale .ROOT )).fromDate (dateReference ()), timezone );
539539 }
540540
541+ /**
542+ * Creates new {@link AggregationExpression} that truncates a date to the given {@literal unit}.
543+ *
544+ * @param unit the unit of measure. Must not be {@literal null}.
545+ * @return new instance of {@link DateTrunc}.
546+ * @since 4.0
547+ */
548+ public DateTrunc truncate (String unit ) {
549+
550+ Assert .notNull (unit , "TemporalUnit must not be null" );
551+ return applyTimezone (DateTrunc .truncateValue (dateReference ()).to (unit ), timezone );
552+ }
553+
554+ /**
555+ * Creates new {@link AggregationExpression} that truncates a date to the given {@literal unit}.
556+ *
557+ * @param unit the unit of measure. Must not be {@literal null}.
558+ * @return new instance of {@link DateTrunc}.
559+ * @since 4.0
560+ */
561+ public DateTrunc truncate (TemporalUnit unit ) {
562+
563+ Assert .notNull (unit , "TemporalUnit must not be null" );
564+ return truncate (unit .name ().toLowerCase (Locale .ROOT ));
565+ }
566+
541567 /**
542568 * Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and
543569 * 366.
@@ -3027,6 +3053,135 @@ protected String getMongoMethod() {
30273053 }
30283054 }
30293055
3056+ /**
3057+ * {@link AggregationExpression} for {@code $dateTrunc}.<br />
3058+ * <strong>NOTE:</strong> Requires MongoDB 5.0 or later.
3059+ *
3060+ * @author Christoph Strobl
3061+ * @since 4.0
3062+ */
3063+ public static class DateTrunc extends TimezonedDateAggregationExpression {
3064+
3065+ private DateTrunc (Object value ) {
3066+ super (value );
3067+ }
3068+
3069+ /**
3070+ * Truncates the date value of computed by the given {@link AggregationExpression}.
3071+ *
3072+ * @param expression must not be {@literal null}.
3073+ * @return new instance of {@link DateTrunc}.
3074+ */
3075+ public static DateTrunc truncateValueOf (AggregationExpression expression ) {
3076+ return truncateValue (expression );
3077+ }
3078+
3079+ /**
3080+ * Truncates the date value of the referenced {@literal field}.
3081+ *
3082+ * @param fieldReference must not be {@literal null}.
3083+ * @return new instance of {@link DateTrunc}.
3084+ */
3085+ public static DateTrunc truncateValueOf (String fieldReference ) {
3086+ return truncateValue (Fields .field (fieldReference ));
3087+ }
3088+
3089+ /**
3090+ * Truncates the date value.
3091+ *
3092+ * @param value must not be {@literal null}.
3093+ * @return new instance of {@link DateTrunc}.
3094+ */
3095+ public static DateTrunc truncateValue (Object value ) {
3096+ return new DateTrunc (Collections .singletonMap ("date" , value ));
3097+ }
3098+
3099+ /**
3100+ * Define the unit of time.
3101+ *
3102+ * @param unit must not be {@literal null}.
3103+ * @return new instance of {@link DateTrunc}.
3104+ */
3105+ public DateTrunc to (String unit ) {
3106+ return new DateTrunc (append ("unit" , unit ));
3107+ }
3108+
3109+ /**
3110+ * Define the unit of time via an {@link AggregationExpression}.
3111+ *
3112+ * @param unit must not be {@literal null}.
3113+ * @return new instance of {@link DateTrunc}.
3114+ */
3115+ public DateTrunc to (AggregationExpression unit ) {
3116+ return new DateTrunc (append ("unit" , unit ));
3117+ }
3118+
3119+ /**
3120+ * Define the weeks starting day if {@link #to(String)} resolves to {@literal week}.
3121+ *
3122+ * @param day must not be {@literal null}.
3123+ * @return new instance of {@link DateTrunc}.
3124+ */
3125+ public DateTrunc startOfWeek (java .time .DayOfWeek day ) {
3126+ return startOfWeek (day .name ().toLowerCase (Locale .US ));
3127+ }
3128+
3129+ /**
3130+ * Define the weeks starting day if {@link #to(String)} resolves to {@literal week}.
3131+ *
3132+ * @param day must not be {@literal null}.
3133+ * @return new instance of {@link DateTrunc}.
3134+ */
3135+ public DateTrunc startOfWeek (String day ) {
3136+ return new DateTrunc (append ("startOfWeek" , day ));
3137+ }
3138+
3139+ /**
3140+ * Define the numeric time value.
3141+ *
3142+ * @param binSize must not be {@literal null}.
3143+ * @return new instance of {@link DateTrunc}.
3144+ */
3145+ public DateTrunc binSize (int binSize ) {
3146+ return binSize ((Object ) binSize );
3147+ }
3148+
3149+ /**
3150+ * Define the numeric time value via an {@link AggregationExpression}.
3151+ *
3152+ * @param expression must not be {@literal null}.
3153+ * @return new instance of {@link DateTrunc}.
3154+ */
3155+ public DateTrunc binSize (AggregationExpression expression ) {
3156+ return binSize ((Object ) expression );
3157+ }
3158+
3159+ /**
3160+ * Define the numeric time value.
3161+ *
3162+ * @param binSize must not be {@literal null}.
3163+ * @return new instance of {@link DateTrunc}.
3164+ */
3165+ public DateTrunc binSize (Object binSize ) {
3166+ return new DateTrunc (append ("binSize" , binSize ));
3167+ }
3168+
3169+ /**
3170+ * Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used.
3171+ *
3172+ * @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead.
3173+ * @return new instance of {@link DateTrunc}.
3174+ */
3175+ public DateTrunc withTimezone (Timezone timezone ) {
3176+ return new DateTrunc (appendTimezone (argumentMap (), timezone ));
3177+ }
3178+
3179+ @ Override
3180+ protected String getMongoMethod () {
3181+ return "$dateTrunc" ;
3182+ }
3183+ }
3184+
30303185 /**
30313186 * Interface defining a temporal unit for date operators.
30323187 *
0 commit comments