19 * |
19 * |
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
21 * or visit www.oracle.com if you need additional information or have any |
21 * or visit www.oracle.com if you need additional information or have any |
22 * questions. |
22 * questions. |
23 */ |
23 */ |
24 import java.util.Calendar; |
24 import java.io.ByteArrayInputStream; |
25 import java.util.GregorianCalendar; |
25 import java.io.ByteArrayOutputStream; |
|
26 import java.io.IOException; |
|
27 import java.time.Month; |
|
28 import java.time.ZoneId; |
|
29 import java.time.ZoneOffset; |
|
30 import java.time.ZonedDateTime; |
26 import java.util.Locale; |
31 import java.util.Locale; |
|
32 import java.util.Properties; |
|
33 import java.util.function.Supplier; |
27 import java.util.logging.Level; |
34 import java.util.logging.Level; |
|
35 import java.util.logging.LogManager; |
28 import java.util.logging.LogRecord; |
36 import java.util.logging.LogRecord; |
29 import java.util.logging.XMLFormatter; |
37 import java.util.logging.XMLFormatter; |
30 |
38 |
31 /** |
39 /** |
32 * @test |
40 * @test |
33 * @bug 8028185 |
41 * @bug 8028185 |
34 * @summary XMLFormatter.format emits incorrect year (year + 1900) |
42 * @summary XMLFormatter.format emits incorrect year (year + 1900) |
35 * @author dfuchs |
43 * @author dfuchs |
|
44 * @run main/othervm XMLFormatterDate |
36 */ |
45 */ |
37 public class XMLFormatterDate { |
46 public class XMLFormatterDate { |
|
47 |
|
48 static final class TimeStamp { |
|
49 |
|
50 final ZonedDateTime zdt; |
|
51 TimeStamp(ZoneId zoneId) { |
|
52 zdt = ZonedDateTime.now(zoneId); |
|
53 } |
|
54 int getYear() { |
|
55 return zdt.getYear(); |
|
56 } |
|
57 boolean isJanuaryFirst() { |
|
58 return zdt.getMonth() == Month.JANUARY && zdt.getDayOfMonth() == 1; |
|
59 } |
|
60 } |
|
61 |
38 |
62 |
39 /** |
63 /** |
40 * Before the fix, JDK8 prints: {@code |
64 * Before the fix, JDK8 prints: {@code |
41 * <record> |
65 * <record> |
42 * <date>3913-11-18T17:35:40</date> |
66 * <date>3913-11-18T17:35:40</date> |
62 public static void main(String[] args) { |
86 public static void main(String[] args) { |
63 Locale locale = Locale.getDefault(); |
87 Locale locale = Locale.getDefault(); |
64 try { |
88 try { |
65 Locale.setDefault(Locale.ENGLISH); |
89 Locale.setDefault(Locale.ENGLISH); |
66 |
90 |
67 final GregorianCalendar cal1 = new GregorianCalendar(); |
91 // Test with default format: by default date is in UTC. |
68 final int year1 = cal1.get(Calendar.YEAR); |
92 System.out.println("Testing with UTC"); |
|
93 test(() -> new TimeStamp(ZoneOffset.UTC)); |
69 |
94 |
70 LogRecord record = new LogRecord(Level.INFO, "test"); |
95 // Change LogManager configuration so that new |
71 XMLFormatter formatter = new XMLFormatter(); |
96 // XMLFormatter prints date in the pre Java 9 local zone format |
72 final String formatted = formatter.format(record); |
97 try { |
73 System.out.println(formatted); |
98 Properties props = new Properties(); |
74 |
99 props.setProperty("java.util.logging.XMLFormatter.useInstant", "false"); |
75 final GregorianCalendar cal2 = new GregorianCalendar(); |
100 ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
76 final int year2 = cal2.get(Calendar.YEAR); |
101 props.store(baos, ""); |
77 if (year2 < 1900) { |
102 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
78 throw new Error("Invalid system year: " + year2); |
103 LogManager.getLogManager().updateConfiguration(bais, (k) -> (o,n) -> n!=null?n:o); |
|
104 } catch (IOException io) { |
|
105 throw new RuntimeException(io); |
79 } |
106 } |
80 |
107 |
81 StringBuilder buf2 = new StringBuilder() |
108 // re test with the old format: date will be in the local time zone. |
82 .append("<date>").append(year2).append("-"); |
109 System.out.println("Testing with old format"); |
83 if (!formatted.contains(buf2.toString())) { |
110 test(() -> new TimeStamp(ZoneId.systemDefault())); |
84 StringBuilder buf1 = new StringBuilder() |
111 |
85 .append("<date>").append(year1).append("-"); |
|
86 if (formatted.contains(buf1) |
|
87 && year2 == year1 + 1 |
|
88 && cal2.get(Calendar.MONTH) == Calendar.JANUARY |
|
89 && cal2.get(Calendar.DAY_OF_MONTH) == 1) { |
|
90 // Oh! The year just switched in the midst of the test... |
|
91 System.out.println("Happy new year!"); |
|
92 } else { |
|
93 throw new Error("Expected year " + year2 |
|
94 + " not found in log:\n" + formatted); |
|
95 } |
|
96 } |
|
97 } finally { |
112 } finally { |
98 Locale.setDefault(locale); |
113 Locale.setDefault(locale); |
99 } |
114 } |
100 } |
115 } |
101 |
116 |
|
117 static void test(Supplier<TimeStamp> timeStampSupplier) { |
|
118 |
|
119 TimeStamp t1 = timeStampSupplier.get(); |
|
120 int year1 = t1.getYear(); |
|
121 |
|
122 LogRecord record = new LogRecord(Level.INFO, "test"); |
|
123 XMLFormatter formatter = new XMLFormatter(); |
|
124 final String formatted = formatter.format(record); |
|
125 System.out.println(formatted); |
|
126 |
|
127 final TimeStamp t2 = timeStampSupplier.get(); |
|
128 final int year2 = t2.getYear(); |
|
129 if (year2 < 1900) { |
|
130 throw new Error("Invalid system year: " + year2); |
|
131 } |
|
132 |
|
133 final StringBuilder buf2 = new StringBuilder() |
|
134 .append("<date>").append(year2).append("-"); |
|
135 if (!formatted.contains(buf2.toString())) { |
|
136 StringBuilder buf1 = new StringBuilder() |
|
137 .append("<date>").append(year1).append("-"); |
|
138 if (formatted.contains(buf1) && year2 == year1 + 1 |
|
139 && t2.isJanuaryFirst()) { |
|
140 // Oh! The year just switched in the midst of the test... |
|
141 System.out.println("Happy new year!"); |
|
142 } else { |
|
143 throw new Error("Expected year " + year2 |
|
144 + " not found in log:\n" + formatted); |
|
145 } |
|
146 } |
|
147 } |
|
148 |
102 } |
149 } |