1717package org .apache .logging .log4j .core .util .internal .instant ;
1818
1919import static java .util .Arrays .asList ;
20- import static java .util .Collections .singletonList ;
2120import static org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .sequencePattern ;
2221import static org .assertj .core .api .Assertions .assertThat ;
2322
3231import java .util .stream .IntStream ;
3332import java .util .stream .Stream ;
3433import org .apache .logging .log4j .core .time .MutableInstant ;
35- import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .CompositePatternSequence ;
36- import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .DynamicPatternSequence ;
37- import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .PatternSequence ;
38- import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .StaticPatternSequence ;
34+ import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .DateTimeFormatterPatternFormatterFactory ;
35+ import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .PatternFormatterFactory ;
36+ import org .apache .logging .log4j .core .util .internal .instant .InstantPatternDynamicFormatter .SecondPatternFormatterFactory ;
3937import org .apache .logging .log4j .util .Constants ;
4038import org .junit .jupiter .params .ParameterizedTest ;
4139import org .junit .jupiter .params .provider .Arguments ;
@@ -47,112 +45,81 @@ class InstantPatternDynamicFormatterTest {
4745 @ ParameterizedTest
4846 @ MethodSource ("sequencingTestCases" )
4947 void sequencing_should_work (
50- final String pattern , final ChronoUnit thresholdPrecision , final List <PatternSequence > expectedSequences ) {
51- final List <PatternSequence > actualSequences = sequencePattern (pattern , thresholdPrecision );
48+ final String pattern ,
49+ final ChronoUnit thresholdPrecision ,
50+ final List <PatternFormatterFactory > expectedSequences ) {
51+ final List <PatternFormatterFactory > actualSequences = sequencePattern (pattern , thresholdPrecision );
5252 assertThat (actualSequences ).isEqualTo (expectedSequences );
5353 }
5454
5555 static List <Arguments > sequencingTestCases () {
5656 final List <Arguments > testCases = new ArrayList <>();
5757
5858 // `SSSX` should be treated constant for daily updates
59- testCases .add (Arguments .of ("SSSX" , ChronoUnit .DAYS , singletonList ( pCom ( pDyn ( "SSS" ), pDyn ("X" ) ))));
59+ testCases .add (Arguments .of ("SSSX" , ChronoUnit .DAYS , asList ( pMilliSec ( ), pDyn ("X" ))));
6060
6161 // `yyyyMMddHHmmssSSSX` instant cache updated hourly
6262 testCases .add (Arguments .of (
6363 "yyyyMMddHHmmssSSSX" ,
6464 ChronoUnit .HOURS ,
65- asList (
66- pCom (pDyn ("yyyy" ), pDyn ("MM" ), pDyn ("dd" ), pDyn ("HH" )),
67- pCom (pDyn ("mm" ), pDyn ("ss" ), pDyn ("SSS" )),
68- pDyn ("X" ))));
65+ asList (pDyn ("yyyyMMddHH" , ChronoUnit .HOURS ), pDyn ("mm" ), pSec ("" , 3 ), pDyn ("X" ))));
6966
7067 // `yyyyMMddHHmmssSSSX` instant cache updated per minute
7168 testCases .add (Arguments .of (
7269 "yyyyMMddHHmmssSSSX" ,
7370 ChronoUnit .MINUTES ,
74- asList (
75- pCom (pDyn ("yyyy" ), pDyn ("MM" ), pDyn ("dd" ), pDyn ("HH" ), pDyn ("mm" )),
76- pCom (pDyn ("ss" ), pDyn ("SSS" )),
77- pDyn ("X" ))));
71+ asList (pDyn ("yyyyMMddHHmm" , ChronoUnit .MINUTES ), pSec ("" , 3 ), pDyn ("X" ))));
7872
7973 // ISO9601 instant cache updated daily
8074 final String iso8601InstantPattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX" ;
8175 testCases .add (Arguments .of (
8276 iso8601InstantPattern ,
8377 ChronoUnit .DAYS ,
8478 asList (
85- pCom (pDyn ("yyyy" ), pSta ("-" ), pDyn ("MM" ), pSta ("-" ), pDyn ("dd" ), pSta ("T" )),
86- pCom (
87- pDyn ("HH" ),
88- pSta (":" ),
89- pDyn ("mm" ),
90- pSta (":" ),
91- pDyn ("ss" ),
92- pSta ("." ),
93- pDyn ("SSS" ),
94- pDyn ("X" )))));
79+ pDyn ("yyyy'-'MM'-'dd'T'" , ChronoUnit .DAYS ),
80+ pDyn ("HH':'mm':'" , ChronoUnit .MINUTES ),
81+ pSec ("." , 3 ),
82+ pDyn ("X" ))));
9583
9684 // ISO9601 instant cache updated per minute
9785 testCases .add (Arguments .of (
9886 iso8601InstantPattern ,
9987 ChronoUnit .MINUTES ,
100- asList (
101- pCom (
102- pDyn ("yyyy" ),
103- pSta ("-" ),
104- pDyn ("MM" ),
105- pSta ("-" ),
106- pDyn ("dd" ),
107- pSta ("T" ),
108- pDyn ("HH" ),
109- pSta (":" ),
110- pDyn ("mm" ),
111- pSta (":" )),
112- pCom (pDyn ("ss" ), pSta ("." ), pDyn ("SSS" )),
113- pDyn ("X" ))));
88+ asList (pDyn ("yyyy'-'MM'-'dd'T'HH':'mm':'" , ChronoUnit .MINUTES ), pSec ("." , 3 ), pDyn ("X" ))));
11489
11590 // ISO9601 instant cache updated per second
11691 testCases .add (Arguments .of (
11792 iso8601InstantPattern ,
11893 ChronoUnit .SECONDS ,
119- asList (
120- pCom (
121- pDyn ("yyyy" ),
122- pSta ("-" ),
123- pDyn ("MM" ),
124- pSta ("-" ),
125- pDyn ("dd" ),
126- pSta ("T" ),
127- pDyn ("HH" ),
128- pSta (":" ),
129- pDyn ("mm" ),
130- pSta (":" ),
131- pDyn ("ss" ),
132- pSta ("." )),
133- pDyn ("SSS" ),
134- pDyn ("X" ))));
94+ asList (pDyn ("yyyy'-'MM'-'dd'T'HH':'mm':'" , ChronoUnit .MINUTES ), pSec ("." , 3 ), pDyn ("X" ))));
95+
96+ // Seconds and micros
97+ testCases .add (Arguments .of (
98+ "HH:mm:ss.SSSSSS" , ChronoUnit .MINUTES , asList (pDyn ("HH':'mm':'" , ChronoUnit .MINUTES ), pSec ("." , 6 ))));
13599
136100 return testCases ;
137101 }
138102
139- private static CompositePatternSequence pCom (final PatternSequence ... sequences ) {
140- return new CompositePatternSequence (asList (sequences ));
103+ private static DateTimeFormatterPatternFormatterFactory pDyn (final String pattern ) {
104+ return new DateTimeFormatterPatternFormatterFactory (pattern );
105+ }
106+
107+ private static DateTimeFormatterPatternFormatterFactory pDyn (final String pattern , final ChronoUnit precision ) {
108+ return new DateTimeFormatterPatternFormatterFactory (pattern , precision );
141109 }
142110
143- private static DynamicPatternSequence pDyn ( final String pattern ) {
144- return new DynamicPatternSequence ( pattern );
111+ private static SecondPatternFormatterFactory pSec ( String separator , int fractionalDigits ) {
112+ return new SecondPatternFormatterFactory ( true , separator , fractionalDigits );
145113 }
146114
147- private static StaticPatternSequence pSta ( final String literal ) {
148- return new StaticPatternSequence ( literal );
115+ private static SecondPatternFormatterFactory pMilliSec ( ) {
116+ return new SecondPatternFormatterFactory ( false , "" , 3 );
149117 }
150118
151119 @ ParameterizedTest
152120 @ ValueSource (
153121 strings = {
154122 // Basics
155- "S" ,
156123 "SSSSSSS" ,
157124 "SSSSSSSSS" ,
158125 "n" ,
@@ -163,8 +130,7 @@ private static StaticPatternSequence pSta(final String literal) {
163130 "yyyy-MM-dd HH:mm:ss,SSSSSSS" ,
164131 "yyyy-MM-dd HH:mm:ss,SSSSSSSS" ,
165132 "yyyy-MM-dd HH:mm:ss,SSSSSSSSS" ,
166- "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS" ,
167- "yyyy-MM-dd'T'HH:mm:ss.SXXX"
133+ "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS"
168134 })
169135 void should_recognize_patterns_of_nano_precision (final String pattern ) {
170136 assertPatternPrecision (pattern , ChronoUnit .NANOS );
@@ -351,7 +317,9 @@ static Stream<Arguments> formatterInputs(final String pattern) {
351317
352318 private static MutableInstant randomInstant () {
353319 final MutableInstant instant = new MutableInstant ();
354- final long epochSecond = RANDOM .nextInt (1_621_280_470 ); // 2021-05-17 21:41:10
320+ // In the 1970's some time zones had sub-minute offsets to UTC, e.g., Africa/Monrovia
321+ final int startEighties = 315_532_800 ;
322+ final long epochSecond = startEighties + RANDOM .nextInt (1_621_280_470 - startEighties ); // 2021-05-17 21:41:10
355323 final int epochSecondNano = randomNanos ();
356324 instant .initFromEpochSecond (epochSecond , epochSecondNano );
357325 return instant ;
0 commit comments