blob: 4b102a4bdda1f710fe2af943ce0608c22d229cfc [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.solr.util;
import java.lang.invoke.MethodHandles;
import java.util.HashSet;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import org.apache.lucene.tests.util.TestUtil;
import org.apache.solr.SolrTestCase;
import org.apache.solr.common.util.SuppressForbidden;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TimeZoneUtilsTest extends SolrTestCase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static void assertSameRules(
final String label, final TimeZone expected, final TimeZone actual) {
if (null == expected && null == actual) return;
assertNotNull(label + ": expected is null", expected);
assertNotNull(label + ": actual is null", actual);
final boolean same = expected.hasSameRules(actual);
assertTrue(label + ": " + expected + " [[NOT SAME RULES]] " + actual, same);
}
@SuppressForbidden(reason = "Using TimeZone.getDisplayName() just for warning purpose in a test")
public void testValidIds() {
final Set<String> idsTested = new HashSet<>();
int skipped = 0;
// brain dead: anything the JVM supports, should work
for (String validId : TimeZone.getAvailableIDs()) {
assertTrue(
validId + " not found in list of known ids",
TimeZoneUtils.KNOWN_TIMEZONE_IDS.contains(validId));
final TimeZone expected = TimeZone.getTimeZone(validId);
final TimeZone actual = TimeZoneUtils.getTimeZone(validId);
// Hack: Why do some timezones have useDaylightTime() as true, but DST as 0?
// It causes an exception during String.valueOf(actual/expected)
if (expected.useDaylightTime() && expected.getDSTSavings() == 0
|| actual.useDaylightTime() && actual.getDSTSavings() == 0) {
if (log.isWarnEnabled()) {
log.warn(
"Not expecting DST to be 0 for {} " + " (actual: {})",
expected.getDisplayName(),
actual.getDisplayName());
}
skipped++;
continue;
}
assertSameRules(validId, expected, actual);
idsTested.add(validId);
}
assertEquals(
"TimeZone.getAvailableIDs vs TimeZoneUtils.KNOWN_TIMEZONE_IDS",
TimeZoneUtils.KNOWN_TIMEZONE_IDS.size() - skipped,
idsTested.size());
}
public void testCustom() {
for (String input :
new String[] {
"GMT-00",
"GMT+00",
"GMT-0",
"GMT+0",
"GMT+08",
"GMT+8",
"GMT-08",
"GMT-8",
"GMT+0800",
"GMT+08:00",
"GMT-0800",
"GMT-08:00",
"GMT+23",
"GMT+2300",
"GMT-23",
"GMT-2300"
}) {
assertSameRules(input, TimeZone.getTimeZone(input), TimeZoneUtils.getTimeZone(input));
}
}
public void testStupidIKnowButIDontTrustTheJVM() {
for (String input :
new String[] {
"GMT-00",
"GMT+00",
"GMT-0",
"GMT+0",
"GMT+08",
"GMT+8",
"GMT-08",
"GMT-8",
"GMT+0800",
"GMT+08:00",
"GMT-0800",
"GMT-08:00",
"GMT+23",
"GMT+2300",
"GMT-23",
"GMT-2300"
}) {
assertSameRules(input, TimeZone.getTimeZone(input), TimeZone.getTimeZone(input));
}
}
public void testInvalidInput() {
final String giberish = "giberish";
assumeFalse(
"This test assumes that " + giberish + " is not a valid tz id",
TimeZoneUtils.KNOWN_TIMEZONE_IDS.contains(giberish));
assertNull(giberish, TimeZoneUtils.getTimeZone(giberish));
for (String malformed :
new String[] {
"GMT+72", "GMT0800",
"GMT+2400", "GMT+24:00",
"GMT+11-30", "GMT+11:-30",
"GMT+0080", "GMT+00:80"
}) {
assertNull(malformed, TimeZoneUtils.getTimeZone(malformed));
}
}
public void testRandom() {
final String ONE_DIGIT = "%1d";
final String TWO_DIGIT = "%02d";
final Random r = random();
final int iters = atLeast(r, 50);
for (int i = 0; i <= iters; i++) {
int hour = TestUtil.nextInt(r, 0, 23);
int min = TestUtil.nextInt(r, 0, 59);
String hours = String.format(Locale.ROOT, (r.nextBoolean() ? ONE_DIGIT : TWO_DIGIT), hour);
String mins = String.format(Locale.ROOT, TWO_DIGIT, min);
String input =
"GMT"
+ (r.nextBoolean() ? "+" : "-")
+ hours
+ (r.nextBoolean() ? "" : ((r.nextBoolean() ? ":" : "") + mins));
assertSameRules(input, TimeZone.getTimeZone(input), TimeZoneUtils.getTimeZone(input));
}
}
}