1 /* 2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * This file is available under and governed by the GNU General Public 26 * License version 2 only, as published by the Free Software Foundation. 27 * However, the following notice accompanied the original version of this 28 * file: 29 * 30 * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos 31 * 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions are met: 36 * 37 * * Redistributions of source code must retain the above copyright notice, 38 * this list of conditions and the following disclaimer. 39 * 40 * * Redistributions in binary form must reproduce the above copyright notice, 41 * this list of conditions and the following disclaimer in the documentation 42 * and/or other materials provided with the distribution. 43 * 44 * * Neither the name of JSR-310 nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 49 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 50 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 51 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 52 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 56 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 */ 60 61 /* 62 * @test 63 * @modules jdk.localedata 64 */ 65 package test.java.time.format; 66 67 import java.time.chrono.ChronoLocalDate; 68 import java.time.chrono.Chronology; 69 import java.time.chrono.IsoChronology; 70 import java.time.chrono.JapaneseChronology; 71 import java.time.chrono.JapaneseEra; 72 import java.time.chrono.MinguoChronology; 73 import java.time.chrono.ThaiBuddhistChronology; 74 import java.time.format.DateTimeFormatter; 75 import java.time.format.DateTimeFormatterBuilder; 76 import java.time.format.FormatStyle; 77 import java.time.LocalDate; 78 import java.time.temporal.ChronoField; 79 import java.time.temporal.Temporal; 80 81 import java.util.HashMap; 82 import java.util.Locale; 83 import java.util.Map; 84 85 import static org.testng.Assert.assertEquals; 86 87 import org.testng.annotations.BeforeMethod; 88 import org.testng.annotations.DataProvider; 89 import org.testng.annotations.Test; 90 91 /** 92 * Test DateTimeFormatterBuilder. 93 */ 94 @Test 95 public class TestDateTimeFormatterBuilderWithLocale { 96 97 private DateTimeFormatterBuilder builder; 98 99 @BeforeMethod 100 public void setUp() { 101 builder = new DateTimeFormatterBuilder(); 102 } 103 104 //----------------------------------------------------------------------- 105 @DataProvider(name="patternPrint") 106 Object[][] data_patternPrint() { 107 return new Object[][] { 108 {"Q", date(2012, 2, 10), "1"}, 109 {"QQ", date(2012, 2, 10), "01"}, 110 {"QQQ", date(2012, 2, 10), "Q1"}, 111 {"QQQQ", date(2012, 2, 10), "1st quarter"}, 112 {"QQQQQ", date(2012, 2, 10), "1"}, 113 }; 114 } 115 116 @Test(dataProvider="patternPrint") 117 public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { 118 DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); 119 String test = f.format(temporal); 120 assertEquals(test, expected); 121 } 122 123 //----------------------------------------------------------------------- 124 @DataProvider(name="mapTextLookup") 125 Object[][] data_mapTextLookup() { 126 return new Object[][] { 127 {IsoChronology.INSTANCE.date(1, 1, 1), Locale.ENGLISH}, 128 {JapaneseChronology.INSTANCE.date(JapaneseEra.HEISEI, 1, 1, 8), Locale.ENGLISH}, 129 {MinguoChronology.INSTANCE.date(1, 1, 1), Locale.ENGLISH}, 130 {ThaiBuddhistChronology.INSTANCE.date(1, 1, 1), Locale.ENGLISH}, 131 }; 132 } 133 134 @Test(dataProvider="mapTextLookup") 135 public void test_appendText_mapTextLookup(ChronoLocalDate date, Locale locale) { 136 final String new1st = "1st"; 137 Map<Long, String> yearMap = new HashMap<>(); 138 yearMap.put(1L, new1st); 139 builder.appendText(ChronoField.YEAR_OF_ERA, yearMap); 140 141 String actual = date.format(builder.toFormatter(locale)); 142 assertEquals(actual, new1st); 143 } 144 145 146 //----------------------------------------------------------------------- 147 @DataProvider(name="localePatterns") 148 Object[][] localizedDateTimePatterns() { 149 return new Object[][] { 150 // French Locale and ISO Chronology 151 {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"}, 152 {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"}, 153 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"}, 154 {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"}, 155 {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"}, 156 {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"}, 157 {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"}, 158 {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"}, 159 {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"}, 160 {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"}, 161 {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"}, 162 {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"}, 163 164 // Japanese Locale and JapaneseChronology 165 {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"}, 166 {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"}, 167 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"}, 168 {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"}, 169 {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, 170 {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, 171 {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, 172 {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"}, 173 {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"}, 174 {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"}, 175 {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"}, 176 {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"}, 177 178 // Chinese Local and Chronology 179 {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"}, 180 {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"}, 181 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"}, 182 {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"}, 183 {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, 184 {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, 185 {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, 186 {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"}, 187 {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"}, 188 {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"}, 189 {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"}, 190 {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"}, 191 }; 192 } 193 194 @Test(dataProvider="localePatterns") 195 public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle, 196 Chronology chrono, Locale locale, String expected) { 197 String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale); 198 assertEquals(actual, expected, "Pattern " + convertNonAscii(actual)); 199 } 200 201 /** 202 * Returns a string that includes non-ascii characters after expanding 203 * the non-ascii characters to their Java language \\uxxxx form. 204 * @param input an input string 205 * @return the encoded string. 206 */ 207 private String convertNonAscii(String input) { 208 StringBuilder sb = new StringBuilder(input.length() * 6); 209 for (int i = 0; i < input.length(); i++) { 210 char ch = input.charAt(i); 211 if (ch < 255) { 212 sb.append(ch); 213 } else { 214 sb.append("\\u"); 215 sb.append(Integer.toHexString(ch)); 216 } 217 } 218 return sb.toString(); 219 } 220 221 private static Temporal date(int y, int m, int d) { 222 return LocalDate.of(y, m, d); 223 } 224 }