Path: blob/master/test/jdk/java/text/Format/DateFormat/SDFTCKZoneNamesTest.java
41152 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 821894826* @summary TCK tests that check the time zone names between DFS.getZoneStrings()27* and SDF.format("z*")28* @run main SDFTCKZoneNamesTest29*/30import java.text.*;31import java.util.Calendar;32import java.util.Date;33import java.util.List;34import java.util.Locale;35import java.util.TimeZone;3637public class SDFTCKZoneNamesTest {3839StringBuffer myFormat(Date date, SimpleDateFormat sdf) {40String pattern = sdf.toPattern();41StringBuffer toAppendTo = new StringBuffer("");42boolean inQuote = false;43char prevCh = 0;44char ch;45int count = 0;46for (int i = 0; i < pattern.length(); i++) {47ch = pattern.charAt(i);48if (inQuote) {49if (ch == '\'') {50inQuote = false;51if (count == 0) toAppendTo.append(ch);52else count = 0;53} else {54toAppendTo.append(ch);55count++;56}57} else { // not inQuote58if (ch == '\'') {59inQuote = true;60if (count > 0) {61toAppendTo.append(subFormat(prevCh, count, date, sdf));62count = 0;63prevCh = 0;64}65} else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {66if (ch != prevCh && count > 0) {67toAppendTo.append(subFormat(prevCh, count, date, sdf));68prevCh = ch;69count = 1;70} else {71if (ch != prevCh) prevCh = ch;72count++;73}74} else if (count > 0) {75toAppendTo.append(subFormat(prevCh, count, date, sdf));76toAppendTo.append(ch);77prevCh = 0;78count = 0;79} else toAppendTo.append(ch);80}81}82if (count > 0) {83toAppendTo.append(subFormat(prevCh, count, date, sdf));84}85return toAppendTo;86}8788private String subFormat(char ch, int count, Date date, SimpleDateFormat sdf)89throws IllegalArgumentException {90int value = 0;91int patternCharIndex = -1;92int maxIntCount = 10;93String current = "";94DateFormatSymbols formatData = sdf.getDateFormatSymbols();95Calendar calendar = sdf.getCalendar();96calendar.setTime(date);97NumberFormat nf = sdf.getNumberFormat();98nf.setGroupingUsed(false);99100if ((patternCharIndex = "GyMdkHmsSEDFwWahKz".indexOf(ch)) == -1)101throw new IllegalArgumentException("Illegal pattern character " +102"'" + ch + "'");103switch (patternCharIndex) {104case 0: // 'G' - ERA105value = calendar.get(Calendar.ERA);106current = formatData.getEras()[value];107break;108case 1: // 'y' - YEAR109value = calendar.get(Calendar.YEAR);110111if (count == 2) {112// For formatting, if the number of pattern letters is 2,113// the year is truncated to 2 digits;114current = zeroPaddingNumber(value, 2, 2, nf);115} else {116// otherwise it is interpreted as a number.117current = zeroPaddingNumber(value, count, maxIntCount, nf);118}119120break;121case 2: // 'M' - MONTH122value = calendar.get(Calendar.MONTH);123if (count >= 4)124// DateFormatSymbols::getMonths spec: "If the language requires different forms for formatting125// and stand-alone usages, this method returns month names in the formatting form."126// Because of that only formatting cases patterns may be tested. Like, "MMMM yyyy". Wrong127// pattern: "MMMM".128current = formatData.getMonths()[value];129else if (count == 3)130// DateFormatSymbols::getShortMonths spec: "If the language requires different forms for formatting131// and stand-alone usages, This method returns short month names in the formatting form."132// Because of that only formatting cases patterns may be tested. Like, "MMM yyyy". Wrong pattern:133// "MMM".134current = formatData.getShortMonths()[value];135else136current = zeroPaddingNumber(value + 1, count, maxIntCount, nf);137break;138case 3: // 'd' - DATE139value = calendar.get(Calendar.DATE);140current = zeroPaddingNumber(value, count, maxIntCount, nf);141break;142case 4: // 'k' - HOUR_OF_DAY: 1-based. eg, 23:59 + 1 hour =>> 24:59143if ((value = calendar.get(Calendar.HOUR_OF_DAY)) == 0)144current = zeroPaddingNumber(145calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1,146count, maxIntCount, nf);147else148current = zeroPaddingNumber(value, count, maxIntCount, nf);149break;150case 5: // 'H' - HOUR_OF_DAY:0-based. eg, 23:59 + 1 hour =>> 00:59151value = calendar.get(Calendar.HOUR_OF_DAY);152current = zeroPaddingNumber(value, count, maxIntCount, nf);153break;154case 6: // 'm' - MINUTE155value = calendar.get(Calendar.MINUTE);156current = zeroPaddingNumber(value, count, maxIntCount, nf);157break;158case 7: // 's' - SECOND159value = calendar.get(Calendar.SECOND);160current = zeroPaddingNumber(value, count, maxIntCount, nf);161break;162case 8: // 'S' - MILLISECOND163value = calendar.get(Calendar.MILLISECOND);164/*165if (count > 3)166value = value * (int) Math.pow(10, count - 3);167else if (count == 2)168value = (value + 5) / 10;169else if (count == 1)170value = (value + 50) / 100;171*/172current = zeroPaddingNumber(value, count, maxIntCount, nf);173break;174case 9: // 'E' - DAY_OF_WEEK175value = calendar.get(Calendar.DAY_OF_WEEK);176if (count >= 4)177current = formatData.getWeekdays()[value];178else // count < 4, use abbreviated form if exists179current = formatData.getShortWeekdays()[value];180break;181case 10: // 'D' - DAY_OF_YEAR182value = calendar.get(Calendar.DAY_OF_YEAR);183current = zeroPaddingNumber(value, count, maxIntCount, nf);184break;185case 11: // 'F' - DAY_OF_WEEK_IN_MONTH186value = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH);187current = zeroPaddingNumber(value, count, maxIntCount, nf);188break;189case 12: // 'w' - WEEK_OF_YEAR190value = calendar.get(Calendar.WEEK_OF_YEAR);191current = zeroPaddingNumber(value, count, maxIntCount, nf);192break;193case 13: // 'W' - WEEK_OF_MONTH194value = calendar.get(Calendar.WEEK_OF_MONTH);195current = zeroPaddingNumber(value, count, maxIntCount, nf);196break;197case 14: // 'a' - AM_PM198value = calendar.get(Calendar.AM_PM);199current = formatData.getAmPmStrings()[value];200break;201case 15: // 'h' - HOUR:1-based. eg, 11PM + 1 hour =>> 12 AM202if ((value = calendar.get(Calendar.HOUR)) == 0)203current = zeroPaddingNumber(204calendar.getLeastMaximum(Calendar.HOUR) + 1,205count, maxIntCount, nf);206else207current = zeroPaddingNumber(value, count, maxIntCount, nf);208break;209case 16: // 'K' - HOUR: 0-based. eg, 11PM + 1 hour =>> 0 AM210value = calendar.get(Calendar.HOUR);211current = zeroPaddingNumber(value, count, maxIntCount, nf);212break;213case 17: // 'z' - ZONE_OFFSET214int zoneIndex = getZoneIndex(calendar.getTimeZone().getID(), formatData);215if (zoneIndex == -1) {216StringBuffer zoneString = new StringBuffer();217value = calendar.get(Calendar.ZONE_OFFSET)218+ calendar.get(Calendar.DST_OFFSET);219if (value < 0) {220zoneString.append("GMT-");221value = -value; // suppress the '-' sign for text display.222} else223zoneString.append("GMT+");224zoneString.append(225zeroPaddingNumber((int) (value / (60 * 60 * 1000)), 2, 2, nf));226zoneString.append(':');227zoneString.append(228zeroPaddingNumber(229(int) ((value % (60 * 60 * 1000)) / (60 * 1000)), 2, 2, nf));230current = zoneString.toString();231} else if (calendar.get(Calendar.DST_OFFSET) != 0) {232if (count >= 4)233current = formatData.getZoneStrings()[zoneIndex][3];234else235// count < 4, use abbreviated form if exists236current = formatData.getZoneStrings()[zoneIndex][4];237} else {238if (count >= 4)239current = formatData.getZoneStrings()[zoneIndex][1];240else241current = formatData.getZoneStrings()[zoneIndex][2];242}243break;244}245246return current;247}248249250String zeroPaddingNumber(long value, int minDigits, int maxDigits,251NumberFormat nf) {252nf.setMinimumIntegerDigits(minDigits);253nf.setMaximumIntegerDigits(maxDigits);254return nf.format(value);255}256257258int getZoneIndex(String ID, DateFormatSymbols dfs) {259String[][] zoneStrings = dfs.getZoneStrings();260261for (int index = 0; index < zoneStrings.length; index++) {262if (ID.equalsIgnoreCase(zoneStrings[index][0])) return index;263}264return -1;265}266267268final int second = 1000;269final int minute = 60 * second;270final int hour = 60 * minute;271final int day = 24 * hour;272final int month = 30 * day;273final int year = 365 * day;274final int someday = 30 * year + 3 * month + 19 * day + 5 * hour;275276277/* standalone interface */278public static void main(String argv[]) {279Locale defaultLocale = Locale.getDefault();280SDFTCKZoneNamesTest test = new SDFTCKZoneNamesTest();281282try {283List.of(Locale.ROOT,284Locale.CHINA,285Locale.forLanguageTag("es-419"),286Locale.GERMANY,287Locale.forLanguageTag("hi-IN"),288Locale.JAPAN,289Locale.TAIWAN,290Locale.UK,291Locale.US,292Locale.forLanguageTag("uz-Cyrl-UZ"),293Locale.forLanguageTag("zh-SG"),294Locale.forLanguageTag("zh-HK"),295Locale.forLanguageTag("zh-MO")).stream()296.forEach(l -> {297System.out.printf("Testing locale: %s%n", l);298Locale.setDefault(l);299test.SimpleDateFormat0062();300});301} finally {302Locale.setDefault(defaultLocale);303}304}305306307/**308* Equivalence class partitioning309* with state, input and output values orientation310* for public StringBuffer format(Date date, StringBuffer result, FieldPosition fp),311* <br><b>pre-conditions</b>: patterns: { "'s0mething'z mm::hh,yyyy zz",312* "zzzz",313* "z"} (each pattern contains letter for TIMEZONE_FIELD),314* <br><b>date</b>: a Date object315* <br><b>result</b>: a string316* <br><b>fp</b>: a FieldPosition object with TIMEZONE_FIELD field317* <br><b>output</b>: formatted date as expected.318*/319public void SimpleDateFormat0062() {320boolean passed = true;321String patterns[] = {"'s0mething'z mm::hh,yyyy zz",322"zzzz",323"z"};324SimpleDateFormat sdf = new SimpleDateFormat();325Date date = new Date(1234567890);326for (String[] tz : sdf.getDateFormatSymbols().getZoneStrings()) {327sdf.setTimeZone(TimeZone.getTimeZone(tz[0]));328for (int i = 0; i < patterns.length && passed; i++) {329StringBuffer result = new StringBuffer("qwerty");330FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD);331sdf.applyPattern(patterns[i]);332String expected = new333StringBuffer("qwerty").append(myFormat(date,334sdf)).toString();335String formatted = sdf.format(date, result, fp).toString();336337if (!expected.equals(formatted)) {338System.out.println(339"method format(date, StringBuffer, FieldPosition) formats wrong");340System.out.println(" pattern: " + patterns[i]);341System.out.println(" time zone ID: " + tz[0]);342System.out.println(" expected result: " + expected);343System.out.println(" formatted result: " + formatted);344passed = false;345}346347if (passed && !expected.equals(result.toString())) {348System.out.println(349"method format(Date date, StringBuffer toAppendTo, FieldPosition fp) toAppendTo is not " +350"equal to output");351System.out.println(" pattern: " + patterns[i]);352System.out.println(" time zone ID: " + tz[0]);353System.out.println(" toAppendTo : " + result);354System.out.println(" formatted date: " + formatted);355passed = false;356}357}358}359if(passed)360{361System.out.println("PASSED : OKAY");362}else363{364throw new RuntimeException("FAILED");365}366}367}368369370