1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.time;
18
19 import static org.junit.jupiter.api.Assertions.assertNotEquals;
20 import static org.junit.jupiter.api.Assertions.fail;
21 import static org.junit.jupiter.api.Assumptions.assumeFalse;
22 import static org.junit.jupiter.api.Assumptions.assumeTrue;
23
24 import java.text.DateFormatSymbols;
25 import java.text.ParseException;
26 import java.util.ArrayList;
27 import java.util.Comparator;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Objects;
32 import java.util.TimeZone;
33
34 import org.apache.commons.lang3.AbstractLangTest;
35 import org.apache.commons.lang3.ArraySorter;
36 import org.apache.commons.lang3.JavaVersion;
37 import org.apache.commons.lang3.LocaleUtils;
38 import org.apache.commons.lang3.SystemUtils;
39 import org.junit.jupiter.api.AfterAll;
40 import org.junit.jupiter.api.Test;
41 import org.junit.jupiter.params.ParameterizedTest;
42 import org.junit.jupiter.params.provider.MethodSource;
43 import org.junitpioneer.jupiter.DefaultLocale;
44 import org.junitpioneer.jupiter.DefaultTimeZone;
45 import org.junitpioneer.jupiter.ReadsDefaultLocale;
46 import org.junitpioneer.jupiter.ReadsDefaultTimeZone;
47
48 @DefaultLocale(language = "en")
49 @DefaultTimeZone(TimeZones.GMT_ID)
50 @ReadsDefaultLocale
51 @ReadsDefaultTimeZone
52 public class FastDateParser_TimeZoneStrategyTest extends AbstractLangTest {
53
54 private static final List<Locale> Java11Failures = new ArrayList<>();
55 private static final List<Locale> Java17Failures = new ArrayList<>();
56
57 @AfterAll
58 public static void afterAll() {
59 if (!Java17Failures.isEmpty()) {
60 System.err.printf("Actual failures on Java 17: %,d%n%s%n", Java17Failures.size(), Java17Failures);
61 }
62 if (!Java11Failures.isEmpty()) {
63 System.err.printf("Actual failures on Java 11: %,d%n%s%n", Java11Failures.size(), Java11Failures);
64 }
65 }
66
67 public static Locale[] getAvailableLocalesSorted() {
68 return ArraySorter.sort(Locale.getAvailableLocales(), Comparator.comparing(Locale::toString));
69 }
70
71 @Test
72 public void testLang1219() throws ParseException {
73 final FastDateParser parser = new FastDateParser("dd.MM.yyyy HH:mm:ss z", TimeZone.getDefault(), Locale.GERMAN);
74 final Date summer = parser.parse("26.10.2014 02:00:00 MESZ");
75 final Date standard = parser.parse("26.10.2014 02:00:00 MEZ");
76 assertNotEquals(summer.getTime(), standard.getTime());
77 }
78
79 @ParameterizedTest
80 @MethodSource("org.apache.commons.lang3.time.FastDateParser_TimeZoneStrategyTest#getAvailableLocalesSorted")
81 public void testTimeZoneStrategy_DateFormatSymbols(final Locale locale) {
82 testTimeZoneStrategyPattern_DateFormatSymbols_getZoneStrings(locale);
83 }
84
85 @ParameterizedTest
86 @MethodSource("org.apache.commons.lang3.time.FastDateParser_TimeZoneStrategyTest#getAvailableLocalesSorted")
87 public void testTimeZoneStrategy_TimeZone(final Locale locale) {
88 testTimeZoneStrategyPattern_TimeZone_getAvailableIDs(locale);
89 }
90
91 private void testTimeZoneStrategyPattern(final String languageTag, final String source) throws ParseException {
92 final Locale locale = Locale.forLanguageTag(languageTag);
93 assumeFalse(LocaleUtils.isLanguageUndetermined(locale), () -> toFailureMessage(locale, languageTag));
94 assumeTrue(LocaleUtils.isAvailableLocale(locale), () -> toFailureMessage(locale, languageTag));
95 final TimeZone tzDefault = TimeZone.getTimeZone("Etc/UTC");
96 final FastDateParser parser = new FastDateParser("z", tzDefault, locale);
97 parser.parse(source);
98 testTimeZoneStrategyPattern_TimeZone_getAvailableIDs(locale);
99 }
100
101 private void testTimeZoneStrategyPattern_DateFormatSymbols_getZoneStrings(final Locale locale) {
102 Objects.requireNonNull(locale, "locale");
103 assumeFalse(LocaleUtils.isLanguageUndetermined(locale), () -> toFailureMessage(locale, null));
104 assumeTrue(LocaleUtils.isAvailableLocale(locale), () -> toFailureMessage(locale, null));
105
106 final String[][] zones = ArraySorter.sort(DateFormatSymbols.getInstance(locale).getZoneStrings(),
107 Comparator.comparing(array -> array[0]));
108 for (final String[] zone : zones) {
109 for (int zIndex = 1; zIndex < zone.length; ++zIndex) {
110 final String tzDisplay = zone[zIndex];
111 if (tzDisplay == null) {
112 break;
113 }
114 final TimeZone timeZone = TimeZone.getDefault();
115 final FastDateParser parser = new FastDateParser("z", timeZone, locale);
116
117 try {
118 parser.parse(tzDisplay);
119 } catch (ParseException e) {
120
121
122 final String localeStr = locale.toString();
123 if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_17)
124 && (localeStr.contains("_") || "Coordinated Universal Time".equals(tzDisplay)
125 || "sommartid â Atyrau".equals(tzDisplay))) {
126 Java17Failures.add(locale);
127
128 System.err.printf(
129 "Java %s - Mark as an assumption failure instead of a hard fail: locale = '%s', parse = '%s'%n",
130 SystemUtils.JAVA_VERSION,
131 localeStr, tzDisplay);
132 assumeTrue(false, localeStr);
133 continue;
134 } else if (SystemUtils.IS_JAVA_11
135 && (localeStr.contains("_") || "Coordinated Universal Time".equals(tzDisplay))) {
136 Java11Failures.add(locale);
137
138 System.err.printf(
139 "Java %s %s - Mark as an assumption failure instead of a hard fail: locale = '%s', parse = '%s'%n",
140 SystemUtils.JAVA_VENDOR,
141 SystemUtils.JAVA_VERSION,
142 localeStr, tzDisplay);
143 assumeTrue(false, localeStr);
144 continue;
145 }
146
147 fail(String.format("%s: with locale = %s, zIndex = %,d, tzDisplay = '%s', parser = '%s'", e,
148 localeStr, zIndex, tzDisplay, parser.toString()), e);
149 }
150 }
151 }
152 }
153
154
155
156
157
158
159 private void testTimeZoneStrategyPattern_TimeZone_getAvailableIDs(final Locale locale) {
160 Objects.requireNonNull(locale, "locale");
161 assumeFalse(LocaleUtils.isLanguageUndetermined(locale), () -> toFailureMessage(locale, null));
162 assumeTrue(LocaleUtils.isAvailableLocale(locale), () -> toFailureMessage(locale, null));
163
164 for (final String id : ArraySorter.sort(TimeZone.getAvailableIDs())) {
165 final TimeZone timeZone = TimeZone.getTimeZone(id);
166 final FastDateParser parser = new FastDateParser("z", timeZone, locale);
167 final String displayName = timeZone.getDisplayName(locale);
168 try {
169 parser.parse(displayName);
170 } catch (ParseException e) {
171
172 fail(String.format("%s: with locale = %s, id = '%s', timeZone = %s, displayName = '%s', parser = '%s'", e, locale, id, timeZone, displayName,
173 parser.toStringAll()), e);
174 }
175 }
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189 @Test
190 public void testTimeZoneStrategyPatternPortugal() throws ParseException {
191 testTimeZoneStrategyPattern("pt_PT", "Horário do Meridiano de Greenwich");
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205 @Test
206 public void testTimeZoneStrategyPatternSuriname() throws ParseException {
207 testTimeZoneStrategyPattern("sr_ME_#Cyrl", "Srednje vreme po GriniÄu");
208 }
209
210 private String toFailureMessage(final Locale locale, final String languageTag) {
211 return String.format("locale = %s, languageTag = '%s', isAvailableLocale = %s, isLanguageUndetermined = %s", languageTag, locale,
212 LocaleUtils.isAvailableLocale(locale), LocaleUtils.isLanguageUndetermined(locale));
213 }
214 }