Skip to content

Commit

Permalink
Add warning when using a textual date field specifier with the COMPAT…
Browse files Browse the repository at this point in the history
… locale provider (#112548) (#112709)

Some textual field specifiers change between COMPAT and CLDR, depending on locale
  • Loading branch information
thecoop authored Sep 10, 2024
1 parent 9f8545d commit 00f2058
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 4 deletions.
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
17 changes: 17 additions & 0 deletions server/src/main/java/org/elasticsearch/common/time/DateUtils.java
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();

@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

0 comments on commit 00f2058

Please sign in to comment.