blob: 3fe125d3dfb08bb34e7cc7a88169ae48651457d2 [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.logging.log4j.core.time.internal.format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.core.time.internal.format.FixedDateFormat;
import org.apache.logging.log4j.core.time.internal.format.FixedDateFormat.FixedFormat;
import org.junit.Test;
import static org.apache.logging.log4j.core.time.internal.format.FixedDateFormat.FixedFormat.*;
import static org.junit.Assert.*;
/**
* Tests {@link FixedDateFormat}.
*/
public class FixedDateFormatTest {
private boolean containsNanos(FixedFormat fixedFormat) {
final String pattern = fixedFormat.getPattern();
return pattern.endsWith("n") || pattern.matches(".+n+X*") || pattern.matches(".+n+Z*");
}
@Test
public void testFixedFormat_getDatePatternNullIfNoDateInPattern() {
assertNull(FixedFormat.ABSOLUTE.getDatePattern());
assertNull(FixedFormat.ABSOLUTE_PERIOD.getDatePattern());
}
@Test
public void testFixedFormat_getDatePatternLengthZeroIfNoDateInPattern() {
assertEquals(0, FixedFormat.ABSOLUTE.getDatePatternLength());
assertEquals(0, FixedFormat.ABSOLUTE_PERIOD.getDatePatternLength());
}
@Test
public void testFixedFormat_getFastDateFormatNullIfNoDateInPattern() {
assertNull(FixedFormat.ABSOLUTE.getFastDateFormat());
assertNull(FixedFormat.ABSOLUTE_PERIOD.getFastDateFormat());
}
@Test
public void testFixedFormat_getDatePatternReturnsDatePatternIfExists() {
assertEquals("yyyyMMdd", FixedFormat.COMPACT.getDatePattern());
assertEquals("yyyy-MM-dd ", DEFAULT.getDatePattern());
}
@Test
public void testFixedFormat_getDatePatternLengthReturnsDatePatternLength() {
assertEquals("yyyyMMdd".length(), FixedFormat.COMPACT.getDatePatternLength());
assertEquals("yyyy-MM-dd ".length(), DEFAULT.getDatePatternLength());
}
@Test
public void testFixedFormat_getFastDateFormatNonNullIfDateInPattern() {
assertNotNull(FixedFormat.COMPACT.getFastDateFormat());
assertNotNull(DEFAULT.getFastDateFormat());
assertEquals("yyyyMMdd", FixedFormat.COMPACT.getFastDateFormat().getPattern());
assertEquals("yyyy-MM-dd ", DEFAULT.getFastDateFormat().getPattern());
}
@Test
public void testCreateIfSupported_nonNullIfNameMatches() {
for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
final String[] options = {format.name()};
assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
}
}
@Test
public void testCreateIfSupported_nonNullIfPatternMatches() {
for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
final String[] options = {format.getPattern()};
assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
}
}
@Test
public void testCreateIfSupported_nullIfNameDoesNotMatch() {
final String[] options = {"DEFAULT3"};
assertNull("DEFAULT3", FixedDateFormat.createIfSupported(options));
}
@Test
public void testCreateIfSupported_nullIfPatternDoesNotMatch() {
final String[] options = {"y M d H m s"};
assertNull("y M d H m s", FixedDateFormat.createIfSupported(options));
}
@Test
public void testCreateIfSupported_defaultIfOptionsArrayNull() {
final FixedDateFormat fmt = FixedDateFormat.createIfSupported((String[]) null);
assertEquals(DEFAULT.getPattern(), fmt.getFormat());
}
@Test
public void testCreateIfSupported_defaultIfOptionsArrayEmpty() {
final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[0]);
assertEquals(DEFAULT.getPattern(), fmt.getFormat());
}
@Test
public void testCreateIfSupported_defaultIfOptionsArrayWithSingleNullElement() {
final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[1]);
assertEquals(DEFAULT.getPattern(), fmt.getFormat());
assertEquals(TimeZone.getDefault(), fmt.getTimeZone());
}
@Test
public void testCreateIfSupported_defaultTimeZoneIfOptionsArrayWithSecondNullElement() {
final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[] {DEFAULT.getPattern(), null, ""});
assertEquals(DEFAULT.getPattern(), fmt.getFormat());
assertEquals(TimeZone.getDefault(), fmt.getTimeZone());
}
@Test
public void testCreateIfSupported_customTimeZoneIfOptionsArrayWithTimeZoneElement() {
final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[] {DEFAULT.getPattern(), "+08:00", ""});
assertEquals(DEFAULT.getPattern(), fmt.getFormat());
assertEquals(TimeZone.getTimeZone("GMT+08:00"), fmt.getTimeZone());
}
@Test(expected = NullPointerException.class)
public void testConstructorDisallowsNullFormat() {
new FixedDateFormat(null, TimeZone.getDefault());
}
@Test(expected = NullPointerException.class)
public void testConstructorDisallowsNullTimeZone() {
new FixedDateFormat(FixedFormat.ABSOLUTE, null);
}
@Test
public void testGetFormatReturnsConstructorFixedFormatPattern() {
final FixedDateFormat format = new FixedDateFormat(FixedDateFormat.FixedFormat.ABSOLUTE, TimeZone.getDefault());
assertSame(FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), format.getFormat());
}
@Test
public void testFormatLong() {
final long now = System.currentTimeMillis();
final long start = now - TimeUnit.HOURS.toMillis(25);
final long end = now + TimeUnit.HOURS.toMillis(25);
for (final FixedFormat format : FixedFormat.values()) {
String pattern = format.getPattern();
if (containsNanos(format) || format.getTimeZoneFormat() != null) {
continue; // cannot compile precise timestamp formats with SimpleDateFormat
}
final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
for (long time = start; time < end; time += 12345) {
final String actual = customTF.format(time);
final String expected = simpleDF.format(new Date(time));
assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
}
}
}
@Test
public void testFormatLong_goingBackInTime() {
final long now = System.currentTimeMillis();
final long start = now - TimeUnit.HOURS.toMillis(25);
final long end = now + TimeUnit.HOURS.toMillis(25);
for (final FixedFormat format : FixedFormat.values()) {
String pattern = format.getPattern();
if (containsNanos(format) || format.getTimeZoneFormat() != null) {
continue; // cannot compile precise timestamp formats with SimpleDateFormat
}
final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
for (long time = end; time > start; time -= 12345) {
final String actual = customTF.format(time);
final String expected = simpleDF.format(new Date(time));
assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
}
}
}
@Test
public void testFormatLongCharArrayInt() {
final long now = System.currentTimeMillis();
final long start = now - TimeUnit.HOURS.toMillis(25);
final long end = now + TimeUnit.HOURS.toMillis(25);
final char[] buffer = new char[128];
for (final FixedFormat format : FixedFormat.values()) {
String pattern = format.getPattern();
if (containsNanos(format) || format.getTimeZoneFormat() != null) {
continue; // cannot compile precise timestamp formats with SimpleDateFormat
}
final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
for (long time = start; time < end; time += 12345) {
final int length = customTF.format(time, buffer, 23);
final String actual = new String(buffer, 23, length);
final String expected = simpleDF.format(new Date(time));
assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
}
}
}
@Test
public void testFormatLongCharArrayInt_goingBackInTime() {
final long now = System.currentTimeMillis();
final long start = now - TimeUnit.HOURS.toMillis(25);
final long end = now + TimeUnit.HOURS.toMillis(25);
final char[] buffer = new char[128];
for (final FixedFormat format : FixedFormat.values()) {
String pattern = format.getPattern();
if (containsNanos(format) || format.getTimeZoneFormat() != null) {
continue; // cannot compile precise timestamp formats with SimpleDateFormat
}
final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
for (long time = end; time > start; time -= 12345) {
final int length = customTF.format(time, buffer, 23);
final String actual = new String(buffer, 23, length);
final String expected = simpleDF.format(new Date(time));
assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
}
}
}
@Test
public void testDaylightSavingToSummerTime() throws Exception {
final Calendar calendar = Calendar.getInstance();
calendar.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse("2017-03-12 00:00:00 UTC"));
final SimpleDateFormat usCentral = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", Locale.US);
usCentral.setTimeZone(TimeZone.getTimeZone("US/Central"));
final SimpleDateFormat utc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", Locale.US);
utc.setTimeZone(TimeZone.getTimeZone("UTC"));
final FixedDateFormat fixedUsCentral = FixedDateFormat.create(DEFAULT, TimeZone.getTimeZone("US/Central"));
final FixedDateFormat fixedUtc = FixedDateFormat.create(DEFAULT, TimeZone.getTimeZone("UTC"));
final String[][] expectedDstAndNoDst = {
// US/Central, UTC
{ "2017-03-11 18:00:00,000", "2017-03-12 00:00:00,000" }, //
{ "2017-03-11 19:00:00,000", "2017-03-12 01:00:00,000" }, //
{ "2017-03-11 20:00:00,000", "2017-03-12 02:00:00,000" }, //
{ "2017-03-11 21:00:00,000", "2017-03-12 03:00:00,000" }, //
{ "2017-03-11 22:00:00,000", "2017-03-12 04:00:00,000" }, //
{ "2017-03-11 23:00:00,000", "2017-03-12 05:00:00,000" }, //
{ "2017-03-12 00:00:00,000", "2017-03-12 06:00:00,000" }, //
{ "2017-03-12 01:00:00,000", "2017-03-12 07:00:00,000" }, //
{ "2017-03-12 03:00:00,000", "2017-03-12 08:00:00,000" }, // DST jump at 2am US central time
{ "2017-03-12 04:00:00,000", "2017-03-12 09:00:00,000" }, //
{ "2017-03-12 05:00:00,000", "2017-03-12 10:00:00,000" }, //
{ "2017-03-12 06:00:00,000", "2017-03-12 11:00:00,000" }, //
{ "2017-03-12 07:00:00,000", "2017-03-12 12:00:00,000" }, //
{ "2017-03-12 08:00:00,000", "2017-03-12 13:00:00,000" }, //
{ "2017-03-12 09:00:00,000", "2017-03-12 14:00:00,000" }, //
{ "2017-03-12 10:00:00,000", "2017-03-12 15:00:00,000" }, //
{ "2017-03-12 11:00:00,000", "2017-03-12 16:00:00,000" }, //
{ "2017-03-12 12:00:00,000", "2017-03-12 17:00:00,000" }, //
{ "2017-03-12 13:00:00,000", "2017-03-12 18:00:00,000" }, //
{ "2017-03-12 14:00:00,000", "2017-03-12 19:00:00,000" }, //
{ "2017-03-12 15:00:00,000", "2017-03-12 20:00:00,000" }, //
{ "2017-03-12 16:00:00,000", "2017-03-12 21:00:00,000" }, //
{ "2017-03-12 17:00:00,000", "2017-03-12 22:00:00,000" }, //
{ "2017-03-12 18:00:00,000", "2017-03-12 23:00:00,000" }, // 24
{ "2017-03-12 19:00:00,000", "2017-03-13 00:00:00,000" }, //
{ "2017-03-12 20:00:00,000", "2017-03-13 01:00:00,000" }, //
{ "2017-03-12 21:00:00,000", "2017-03-13 02:00:00,000" }, //
{ "2017-03-12 22:00:00,000", "2017-03-13 03:00:00,000" }, //
{ "2017-03-12 23:00:00,000", "2017-03-13 04:00:00,000" }, //
{ "2017-03-13 00:00:00,000", "2017-03-13 05:00:00,000" }, //
{ "2017-03-13 01:00:00,000", "2017-03-13 06:00:00,000" }, //
{ "2017-03-13 02:00:00,000", "2017-03-13 07:00:00,000" }, //
{ "2017-03-13 03:00:00,000", "2017-03-13 08:00:00,000" }, //
{ "2017-03-13 04:00:00,000", "2017-03-13 09:00:00,000" }, //
{ "2017-03-13 05:00:00,000", "2017-03-13 10:00:00,000" }, //
{ "2017-03-13 06:00:00,000", "2017-03-13 11:00:00,000" }, //
};
final TimeZone tz = TimeZone.getTimeZone("US/Central");
for (int i = 0; i < 36; i++) {
final Date date = calendar.getTime();
assertEquals("SimpleDateFormat TZ=US Central", expectedDstAndNoDst[i][0], usCentral.format(date));
assertEquals("SimpleDateFormat TZ=UTC", expectedDstAndNoDst[i][1], utc.format(date));
assertEquals("FixedDateFormat TZ=US Central", expectedDstAndNoDst[i][0], fixedUsCentral.format(date.getTime()));
assertEquals("FixedDateFormat TZ=UTC", expectedDstAndNoDst[i][1], fixedUtc.format(date.getTime()));
calendar.add(Calendar.HOUR_OF_DAY, 1);
}
}
@Test
public void testDaylightSavingToWinterTime() throws Exception {
final Calendar calendar = Calendar.getInstance();
calendar.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse("2017-11-05 00:00:00 UTC"));
final SimpleDateFormat usCentral = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", Locale.US);
usCentral.setTimeZone(TimeZone.getTimeZone("US/Central"));
final SimpleDateFormat utc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", Locale.US);
utc.setTimeZone(TimeZone.getTimeZone("UTC"));
final FixedDateFormat fixedUsCentral = FixedDateFormat.create(DEFAULT, TimeZone.getTimeZone("US/Central"));
final FixedDateFormat fixedUtc = FixedDateFormat.create(DEFAULT, TimeZone.getTimeZone("UTC"));
final String[][] expectedDstAndNoDst = {
// US/Central, UTC
{ "2017-11-04 19:00:00,000", "2017-11-05 00:00:00,000" }, //
{ "2017-11-04 20:00:00,000", "2017-11-05 01:00:00,000" }, //
{ "2017-11-04 21:00:00,000", "2017-11-05 02:00:00,000" }, //
{ "2017-11-04 22:00:00,000", "2017-11-05 03:00:00,000" }, //
{ "2017-11-04 23:00:00,000", "2017-11-05 04:00:00,000" }, //
{ "2017-11-05 00:00:00,000", "2017-11-05 05:00:00,000" }, //
{ "2017-11-05 01:00:00,000", "2017-11-05 06:00:00,000" }, // DST jump at 2am US central time
{ "2017-11-05 01:00:00,000", "2017-11-05 07:00:00,000" }, //
{ "2017-11-05 02:00:00,000", "2017-11-05 08:00:00,000" }, //
{ "2017-11-05 03:00:00,000", "2017-11-05 09:00:00,000" }, //
{ "2017-11-05 04:00:00,000", "2017-11-05 10:00:00,000" }, //
{ "2017-11-05 05:00:00,000", "2017-11-05 11:00:00,000" }, //
{ "2017-11-05 06:00:00,000", "2017-11-05 12:00:00,000" }, //
{ "2017-11-05 07:00:00,000", "2017-11-05 13:00:00,000" }, //
{ "2017-11-05 08:00:00,000", "2017-11-05 14:00:00,000" }, //
{ "2017-11-05 09:00:00,000", "2017-11-05 15:00:00,000" }, //
{ "2017-11-05 10:00:00,000", "2017-11-05 16:00:00,000" }, //
{ "2017-11-05 11:00:00,000", "2017-11-05 17:00:00,000" }, //
{ "2017-11-05 12:00:00,000", "2017-11-05 18:00:00,000" }, //
{ "2017-11-05 13:00:00,000", "2017-11-05 19:00:00,000" }, //
{ "2017-11-05 14:00:00,000", "2017-11-05 20:00:00,000" }, //
{ "2017-11-05 15:00:00,000", "2017-11-05 21:00:00,000" }, //
{ "2017-11-05 16:00:00,000", "2017-11-05 22:00:00,000" }, //
{ "2017-11-05 17:00:00,000", "2017-11-05 23:00:00,000" }, // 24
{ "2017-11-05 18:00:00,000", "2017-11-06 00:00:00,000" }, //
{ "2017-11-05 19:00:00,000", "2017-11-06 01:00:00,000" }, //
{ "2017-11-05 20:00:00,000", "2017-11-06 02:00:00,000" }, //
{ "2017-11-05 21:00:00,000", "2017-11-06 03:00:00,000" }, //
{ "2017-11-05 22:00:00,000", "2017-11-06 04:00:00,000" }, //
{ "2017-11-05 23:00:00,000", "2017-11-06 05:00:00,000" }, //
{ "2017-11-06 00:00:00,000", "2017-11-06 06:00:00,000" }, //
{ "2017-11-06 01:00:00,000", "2017-11-06 07:00:00,000" }, //
{ "2017-11-06 02:00:00,000", "2017-11-06 08:00:00,000" }, //
{ "2017-11-06 03:00:00,000", "2017-11-06 09:00:00,000" }, //
{ "2017-11-06 04:00:00,000", "2017-11-06 10:00:00,000" }, //
{ "2017-11-06 05:00:00,000", "2017-11-06 11:00:00,000" }, //
};
final TimeZone tz = TimeZone.getTimeZone("US/Central");
for (int i = 0; i < 36; i++) {
final Date date = calendar.getTime();
//System.out.println(usCentral.format(date) + ", Fixed: " + fixedUsCentral.format(date.getTime()) + ", utc: " + utc.format(date));
assertEquals("SimpleDateFormat TZ=US Central", expectedDstAndNoDst[i][0], usCentral.format(date));
assertEquals("SimpleDateFormat TZ=UTC", expectedDstAndNoDst[i][1], utc.format(date));
assertEquals("FixedDateFormat TZ=US Central", expectedDstAndNoDst[i][0], fixedUsCentral.format(date.getTime()));
assertEquals("FixedDateFormat TZ=UTC", expectedDstAndNoDst[i][1], fixedUtc.format(date.getTime()));
calendar.add(Calendar.HOUR_OF_DAY, 1);
}
}
/**
* This test case validates date pattern before and after DST
* Base Date : 12 Mar 2017
* Daylight Savings started on : 02:00 AM
*/
@Test
public void testFormatLong_goingBackInTime_DST() {
final Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("EST"));
instance.set(2017, 2, 12, 2, 0);
final long now = instance.getTimeInMillis();
final long start = now - TimeUnit.HOURS.toMillis(1);
final long end = now + TimeUnit.HOURS.toMillis(1);
for (final FixedFormat format : FixedFormat.values()) {
String pattern = format.getPattern();
if (containsNanos(format) || format.getTimeZoneFormat() != null) {
continue; // cannot compile precise timestamp formats with SimpleDateFormat
}
final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
for (long time = end; time > start; time -= 12345) {
final String actual = customTF.format(time);
final String expected = simpleDF.format(new Date(time));
assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
}
}
}
}