blob: c8a9ccb6f099a449ad68d29f42df94407ab734d0 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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.apache.fineract.infrastructure.core.service;
import static java.time.temporal.ChronoUnit.DAYS;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Locale;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
public final class DateUtils {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATETIME_FORMAT = DEFAULT_DATE_FORMAT + " HH:mm:ss";
public static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT);
public static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT);
private DateUtils() {
}
// DateTime
public static ZoneId getSystemZoneId() {
return ZoneId.systemDefault();
}
public static ZoneId getDateTimeZoneOfTenant() {
final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
return ZoneId.of(tenant.getTimezoneId());
}
public static LocalDate getLocalDateOfTenant() {
return LocalDate.now(getDateTimeZoneOfTenant());
}
public static LocalDateTime getLocalDateTimeOfTenant() {
return getLocalDateTimeOfTenant(null);
}
public static LocalDateTime getLocalDateTimeOfTenant(ChronoUnit truncate) {
LocalDateTime now = LocalDateTime.now(getDateTimeZoneOfTenant());
return truncate == null ? now : now.truncatedTo(truncate);
}
public static OffsetDateTime getOffsetDateTimeOfTenant() {
return getOffsetDateTimeOfTenant(null);
}
public static OffsetDateTime getOffsetDateTimeOfTenant(ChronoUnit truncate) {
OffsetDateTime now = OffsetDateTime.now(getDateTimeZoneOfTenant());
return truncate == null ? now : now.truncatedTo(truncate);
}
public static LocalDateTime getLocalDateTimeOfSystem() {
return getLocalDateTimeOfSystem(null);
}
public static LocalDateTime getLocalDateTimeOfSystem(ChronoUnit truncate) {
LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
return truncate == null ? now : now.truncatedTo(truncate);
}
public static LocalDateTime getAuditLocalDateTime() {
return LocalDateTime.now(ZoneId.of("UTC"));
}
public static OffsetDateTime getAuditOffsetDateTime() {
return OffsetDateTime.now(ZoneOffset.UTC);
}
public static int compare(LocalDateTime first, LocalDateTime second) {
return compare(first, second, null);
}
public static int compare(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) {
if (first == null) {
return second == null ? 0 : -1;
}
if (second == null) {
return 1;
}
return truncate == null ? first.compareTo(second) : first.truncatedTo(truncate).compareTo(second.truncatedTo(truncate));
}
public static boolean isEqual(LocalDateTime first, LocalDateTime second) {
return isEqual(first, second, null);
}
public static boolean isEqual(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) {
return compare(first, second, truncate) == 0;
}
public static boolean isEqualTenantDateTime(LocalDateTime dateTime) {
return isEqualTenantDateTime(dateTime, null);
}
public static boolean isEqualTenantDateTime(LocalDateTime dateTime, ChronoUnit truncate) {
return isEqual(dateTime, getLocalDateTimeOfTenant(), truncate);
}
public static boolean isEqualSystemDateTime(LocalDateTime dateTime) {
return isEqualSystemDateTime(dateTime, null);
}
public static boolean isEqualSystemDateTime(LocalDateTime dateTime, ChronoUnit truncate) {
return isEqual(dateTime, getLocalDateTimeOfSystem(), truncate);
}
public static boolean isBefore(LocalDateTime first, LocalDateTime second) {
return isBefore(first, second, null);
}
public static boolean isBefore(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) {
return compare(first, second, truncate) < 0;
}
public static boolean isBeforeTenantDateTime(LocalDateTime dateTime) {
return isBeforeTenantDateTime(dateTime, null);
}
public static boolean isBeforeTenantDateTime(LocalDateTime dateTime, ChronoUnit truncate) {
return isBefore(dateTime, getLocalDateTimeOfTenant(), truncate);
}
public static boolean isBeforeSystemDateTime(LocalDateTime dateTime) {
return isBeforeSystemDateTime(dateTime, null);
}
public static boolean isBeforeSystemDateTime(LocalDateTime dateTime, ChronoUnit truncate) {
return isBefore(dateTime, getLocalDateTimeOfSystem(), truncate);
}
public static boolean isAfter(LocalDateTime first, LocalDateTime second) {
return isAfter(first, second, null);
}
public static boolean isAfter(LocalDateTime first, LocalDateTime second, ChronoUnit truncate) {
return compare(first, second, truncate) > 0;
}
public static boolean isAfterTenantDateTime(LocalDateTime dateTime) {
return isAfterTenantDateTime(dateTime, null);
}
public static boolean isAfterTenantDateTime(LocalDateTime dateTime, ChronoUnit truncate) {
return isAfter(dateTime, getLocalDateTimeOfTenant(), truncate);
}
public static boolean isAfterSystemDateTime(LocalDateTime dateTime) {
return isAfterSystemDateTime(dateTime, null);
}
public static boolean isAfterSystemDateTime(LocalDateTime dateTime, ChronoUnit truncate) {
return isAfter(dateTime, getLocalDateTimeOfSystem(), truncate);
}
public static int compare(OffsetDateTime first, OffsetDateTime second) {
return compare(first, second, null);
}
public static int compare(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) {
if (first == null) {
return second == null ? 0 : -1;
}
if (second == null) {
return 1;
}
first = first.withOffsetSameInstant(ZoneOffset.UTC);
second = second.withOffsetSameInstant(ZoneOffset.UTC);
return truncate == null ? first.compareTo(second) : first.truncatedTo(truncate).compareTo(second.truncatedTo(truncate));
}
public static boolean isEqual(OffsetDateTime first, OffsetDateTime second) {
return isEqual(first, second, null);
}
public static boolean isEqual(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) {
return compare(first, second, truncate) == 0;
}
public static boolean isEqualTenantDateTime(OffsetDateTime dateTime) {
return isEqualTenantDateTime(dateTime, null);
}
public static boolean isEqualTenantDateTime(OffsetDateTime dateTime, ChronoUnit truncate) {
return isEqual(dateTime, getOffsetDateTimeOfTenant(), truncate);
}
public static boolean isBefore(OffsetDateTime first, OffsetDateTime second) {
return isBefore(first, second, null);
}
public static boolean isBefore(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) {
return compare(first, second, truncate) < 0;
}
public static boolean isBeforeTenantDateTime(OffsetDateTime dateTime) {
return isBeforeTenantDateTime(dateTime, null);
}
public static boolean isBeforeTenantDateTime(OffsetDateTime dateTime, ChronoUnit truncate) {
return isBefore(dateTime, getOffsetDateTimeOfTenant(), truncate);
}
public static boolean isAfter(OffsetDateTime first, OffsetDateTime second) {
return isAfter(first, second, null);
}
public static boolean isAfter(OffsetDateTime first, OffsetDateTime second, ChronoUnit truncate) {
return compare(first, second, truncate) > 0;
}
public static boolean isAfterTenantDateTime(OffsetDateTime dateTime) {
return isAfterTenantDateTime(dateTime, null);
}
public static boolean isAfterTenantDateTime(OffsetDateTime dateTime, ChronoUnit truncate) {
return isAfter(dateTime, getOffsetDateTimeOfTenant(), truncate);
}
// Date
public static LocalDate getBusinessLocalDate() {
return ThreadLocalContextUtil.getBusinessDate();
}
public static int compareToBusinessDate(LocalDate date) {
return compare(date, getBusinessLocalDate());
}
public static boolean isEqualTenantDate(LocalDate date) {
return isEqual(date, getLocalDateOfTenant());
}
public static boolean isBeforeTenantDate(LocalDate date) {
return isBefore(date, getLocalDateOfTenant());
}
public static boolean isAfterTenantDate(LocalDate date) {
return isAfter(date, getLocalDateOfTenant());
}
public static boolean isEqualBusinessDate(LocalDate date) {
return isEqual(date, getBusinessLocalDate());
}
public static boolean isBeforeBusinessDate(LocalDate date) {
return isBefore(date, getBusinessLocalDate());
}
public static boolean isAfterBusinessDate(LocalDate date) {
return isAfter(date, getBusinessLocalDate());
}
public static boolean isDateInTheFuture(final LocalDate localDate) {
return isAfterBusinessDate(localDate);
}
public static int compare(LocalDate first, LocalDate second) {
return first == null ? (second == null ? 0 : -1) : (second == null ? 1 : first.compareTo(second));
}
public static boolean isEqual(LocalDate first, LocalDate second) {
return first == null ? second == null : (second != null && first.isEqual(second));
}
public static boolean isBefore(LocalDate first, LocalDate second) {
return second != null && (first == null || first.isBefore(second));
}
public static boolean isAfter(LocalDate first, LocalDate second) {
return first != null && (second == null || first.isAfter(second));
}
public static long getDifferenceInDays(final LocalDate localDateBefore, final LocalDate localDateAfter) {
return DAYS.between(localDateBefore, localDateAfter);
}
// Parse, format
public static LocalDate parseLocalDate(String stringDate) {
return parseLocalDate(stringDate, null);
}
public static LocalDate parseLocalDate(String stringDate, String format) {
return parseLocalDate(stringDate, format, null);
}
public static LocalDate parseLocalDate(String stringDate, String format, Locale locale) {
if (stringDate == null) {
return null;
}
DateTimeFormatter formatter = getDateFormatter(format, locale);
try {
return LocalDate.parse(stringDate, formatter);
} catch (final DateTimeParseException e) {
final List<ApiParameterError> errors = List.of(ApiParameterError.parameterError("validation.msg.invalid.date.pattern",
"The parameter date (" + stringDate + ") format is invalid", "date", stringDate));
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", errors, e);
}
}
public static String format(LocalDate date) {
return format(date, null);
}
public static String format(LocalDate date, String format) {
return format(date, format, null);
}
public static String format(LocalDate date, String format, Locale locale) {
return date == null ? null : date.format(getDateFormatter(format, locale));
}
public static String format(LocalDateTime dateTime) {
return format(dateTime, null);
}
public static String format(LocalDateTime dateTime, String format) {
return format(dateTime, format, null);
}
public static String format(LocalDateTime dateTime, String format, Locale locale) {
return dateTime == null ? null : dateTime.format(getDateTimeFormatter(format, locale));
}
/**
* Checks if a specific date falls within a given range (inclusive).
*
* @param targetDate
* the date to be checked
* @param startDate
* the start date of the range
* @param endDate
* the end date of the range
* @return true if targetDate is within range or equal to start/end dates, otherwise false
*/
public static boolean isDateWithinRange(LocalDate targetDate, LocalDate startDate, LocalDate endDate) {
if (targetDate == null || startDate == null || endDate == null) {
throw new IllegalArgumentException("Dates must not be null");
}
return !targetDate.isBefore(startDate) && !targetDate.isAfter(endDate);
}
@NotNull
private static DateTimeFormatter getDateFormatter(String format, Locale locale) {
DateTimeFormatter formatter = DEFAULT_DATE_FORMATTER;
if (format != null || locale != null) {
if (format == null) {
format = DEFAULT_DATE_FORMAT;
}
formatter = locale == null ? DateTimeFormatter.ofPattern(format) : DateTimeFormatter.ofPattern(format, locale);
}
return formatter;
}
@NotNull
private static DateTimeFormatter getDateTimeFormatter(String format, Locale locale) {
DateTimeFormatter formatter = DEFAULT_DATETIME_FORMATTER;
if (format != null || locale != null) {
if (format == null) {
format = DEFAULT_DATETIME_FORMAT;
}
formatter = locale == null ? DateTimeFormatter.ofPattern(format) : DateTimeFormatter.ofPattern(format, locale);
}
return formatter;
}
}