Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add warning when using a textual date field specifier with the COMPAT locale provider #112548

Merged
merged 10 commits into from
Sep 10, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -2323,6 +2323,8 @@ static DateFormatter forPattern(String input) {
} else if (FormatNames.STRICT_YEAR_MONTH_DAY.matches(input)) {
return STRICT_YEAR_MONTH_DAY;
} else {
DateUtils.checkTextualDateFormats(input);

try {
return newDateFormatter(
input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

import org.elasticsearch.common.logging.DeprecationCategory;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.core.Predicates;
import org.elasticsearch.core.UpdateForV9;
import org.elasticsearch.logging.LogManager;

import java.time.Clock;
import java.time.Duration;
Expand All @@ -19,6 +22,8 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Pattern;

import static java.util.Map.entry;
import static org.elasticsearch.common.time.DateUtilsRounding.getMonthOfYear;
Expand Down Expand Up @@ -382,4 +387,16 @@ public static ZonedDateTime nowWithMillisResolution(Clock clock) {
Clock millisResolutionClock = Clock.tick(clock, Duration.ofMillis(1));
return ZonedDateTime.now(millisResolutionClock);
}

// check for all textual fields, and localized zone offset
private static final Predicate<String> CONTAINS_CHANGING_TEXT_SPECIFIERS = System.getProperty("java.locale.providers", "")
.contains("COMPAT") ? Pattern.compile("[EcGaO]|MMM|LLL|eee|ccc|QQQ|ZZZZ").asPredicate() : Predicates.never();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are plenty of integration ingest pipelines that instantiate date and date_index_name processors that match this regex.

Is there a way to mitigate the impact for them and reduce the noise from deprecation logs?


@UpdateForV9 // this can be removed, we will only use CLDR on v9
static void checkTextualDateFormats(String format) {
if (CONTAINS_CHANGING_TEXT_SPECIFIERS.test(format)) {
LogManager.getLogger(DateFormatter.class)
.warn("Date format [{}] contains textual field specifiers that could change in JDK 23", format);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ CharSequence buildExpirationMessage(long expirationMillis, boolean expired) {
License [{}] on [{}].
# If you have a new license, please update it. Otherwise, please reach out to
# your support contact.
#\s""", expiredMsg, LicenseUtils.DATE_FORMATTER.formatMillis(expirationMillis));
#\s""", expiredMsg, LicenseUtils.formatMillis(expirationMillis));
if (expired) {
general = general.toUpperCase(Locale.ROOT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@

import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.common.hash.MessageDigests;
import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.license.License.LicenseType;
import org.elasticsearch.license.internal.XPackLicenseStatus;
import org.elasticsearch.protocol.xpack.license.LicenseStatus;
import org.elasticsearch.rest.RestStatus;

import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
Expand All @@ -25,7 +27,13 @@
public class LicenseUtils {

public static final String EXPIRED_FEATURE_METADATA = "es.license.expired.feature";
public static final DateFormatter DATE_FORMATTER = DateFormatter.forPattern("EEEE, MMMM dd, yyyy").withLocale(Locale.ENGLISH);

public static String formatMillis(long millis) {
// DateFormatters logs a warning about the pattern on COMPAT
// this will be confusing to users, so call DateTimeFormatter directly instead
return DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy", Locale.ENGLISH)
.format(Instant.ofEpochMilli(millis).atOffset(ZoneOffset.UTC));
}

/**
* Exception to be thrown when a feature action requires a valid license, but license
Expand Down Expand Up @@ -155,7 +163,7 @@ public static String getExpiryWarning(long licenseExpiryDate, long currentTime)
? "expires today"
: (diff > 0
? String.format(Locale.ROOT, "will expire in [%d] days", days)
: String.format(Locale.ROOT, "expired on [%s]", LicenseUtils.DATE_FORMATTER.formatMillis(licenseExpiryDate)));
: String.format(Locale.ROOT, "expired on [%s]", formatMillis(licenseExpiryDate)));
return "Your license "
+ expiryMessage
+ ". "
Expand Down