package net.time4j.format.expert;
import net.time4j.Moment;
import net.time4j.PlainDate;
import net.time4j.PlainTime;
import net.time4j.PlainTimestamp;
import net.time4j.SI;
import net.time4j.Weekday;
import net.time4j.Weekmodel;
import net.time4j.ZonalDateTime;
import net.time4j.engine.AttributeQuery;
import net.time4j.engine.ChronoDisplay;
import net.time4j.engine.ChronoElement;
import net.time4j.engine.ChronoEntity;
import net.time4j.engine.ChronoFunction;
import net.time4j.format.Attributes;
import net.time4j.format.DisplayMode;
import net.time4j.format.Leniency;
import net.time4j.format.NumberSystem;
import net.time4j.format.PluralCategory;
import net.time4j.format.TemporalFormatter;
import net.time4j.format.TextElement;
import net.time4j.format.TextWidth;
import net.time4j.history.ChronoHistory;
import net.time4j.history.HistoricEra;
import net.time4j.scale.TimeScale;
import net.time4j.tz.NameStyle;
import net.time4j.tz.Timezone;
import net.time4j.tz.ZonalOffset;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.IOException;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import static net.time4j.tz.OffsetSign.AHEAD_OF_UTC;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@RunWith(JUnit4.class)
public class MiscellaneousTest {
@Test
public void printArabicIndicMicroOfDay() {
ChronoFormatter<PlainTime> f =
ChronoFormatter.setUp(PlainTime.axis(), new Locale("en"))
.addLongNumber(PlainTime.MICRO_OF_DAY, 11, 11, SignPolicy.SHOW_NEVER)
.build()
.with(Attributes.NUMBER_SYSTEM, NumberSystem.ARABIC_INDIC);
char zeroChar = NumberSystem.ARABIC_INDIC.getDigits().charAt(0);
StringBuilder zeroes = new StringBuilder();
for (int i = 0; i < 6; i++) {
zeroes.append(zeroChar);
}
assertThat(
f.format(PlainTime.midnightAtEndOfDay()),
is(NumberSystem.ARABIC_INDIC.toNumeral(86400) + zeroes.toString()));
assertThat(
f.with(new Locale("ar")).format(PlainTime.midnightAtEndOfDay()),
is(NumberSystem.ARABIC_INDIC.toNumeral(86400) + zeroes.toString()));
}
@Test
public void localizedStdNumberSystem() {
ChronoFormatter<PlainTime> f =
ChronoFormatter.ofTimePattern("HH:mm", PatternType.CLDR, Locale.ENGLISH);
assertThat(
f.getAttributes().get(Attributes.NUMBER_SYSTEM),
is(NumberSystem.ARABIC));
assertThat(
f.with(new Locale("ar")).getAttributes().get(Attributes.NUMBER_SYSTEM),
is(NumberSystem.ARABIC_INDIC));
assertThat(
f.with(new Locale("ar", "DZ")).getAttributes().get(Attributes.NUMBER_SYSTEM),
is(NumberSystem.ARABIC));
assertThat(
f.with(new Locale("fa")).getAttributes().get(Attributes.NUMBER_SYSTEM),
is(NumberSystem.ARABIC_INDIC_EXT));
assertThat(
f.with(new Locale("my")).getAttributes().get(Attributes.NUMBER_SYSTEM),
is(NumberSystem.MYANMAR));
assertThat(
f.with(new Locale("ne")).getAttributes().get(Attributes.NUMBER_SYSTEM),
is(NumberSystem.DEVANAGARI));
}
@Test
public void testTagalog() throws ParseException {
ChronoFormatter<PlainDate> formatter =
ChronoFormatter.ofDatePattern("MMMM", PatternType.CLDR, new Locale("tl"));
assertThat(
formatter.format(PlainDate.of(2015, 11, 19)),
is("Nobyembre"));
}
@Test(expected=IllegalArgumentException.class)
public void printWithGenericPattern() {
ChronoFormatter<PlainDate> formatter =
ChronoFormatter.ofDatePattern("EEEE, yyyy-MM-dd", PatternType.NON_ISO_DATE, Locale.GERMAN);
formatter.format(PlainDate.of(2015, 7, 17));
}
@Test
public void printLocalDayOfWeekAsText() throws IOException {
TextElement<?> te =
TextElement.class.cast(Weekmodel.of(Locale.US).localDayOfWeek());
Attributes attributes =
new Attributes.Builder()
.setLanguage(Locale.GERMANY)
.build();
Appendable buffer = new StringBuilder();
te.print(PlainDate.of(2013, 3, 8), buffer, attributes);
assertThat(buffer.toString(), is("Freitag"));
}
@Test
public void parseLocalDayOfWeekAsText() throws IOException {
TextElement<?> te =
TextElement.class.cast(Weekmodel.of(Locale.US).localDayOfWeek());
Attributes attributes =
new Attributes.Builder()
.setLanguage(Locale.GERMANY)
.set(Attributes.PARSE_CASE_INSENSITIVE, true)
.build();
ParseLog status = new ParseLog();
Object parseResult = te.parse("FreitaG", status.getPP(), attributes);
assertThat(parseResult.equals(Weekday.FRIDAY), is(true));
assertThat(status.getPosition(), is(7));
assertThat(status.getErrorIndex(), is(-1));
}
@Test
public void changeOfWeekmodelExtensionElement() throws IOException {
PlainDate wednesday = PlainDate.of(2015, 4, 8);
ChronoFormatter<PlainDate> f =
ChronoFormatter.setUp(PlainDate.class, Locale.GERMANY)
.addPattern("e", PatternType.CLDR).build();
String de = f.format(wednesday);
assertThat(de, is("3"));
f = f.with(Locale.US);
String us = f.format(wednesday);
assertThat(us, is("4"));
}
@Test
public void testGenericFullTimeFormats() {
PlainTime time = PlainTime.of(22, 40);
for (Locale loc : DateFormatSymbols.getAvailableLocales()) {
try {
PlainTime.formatter(DisplayMode.FULL, loc).format(time);
} catch (RuntimeException re){
DateFormat df = DateFormat.getTimeInstance(DateFormat.FULL, loc);
String pattern = SimpleDateFormat.class.cast(df).toPattern();
fail("locale=" + loc + ", pattern=[" + pattern + "] => " + re.getMessage() + ")");
}
}
}
@Test
public void testGenericLongTimeFormats() {
PlainTime time = PlainTime.of(22, 40);
for (Locale loc : DateFormatSymbols.getAvailableLocales()) {
try {
PlainTime.formatter(DisplayMode.LONG, loc).format(time);
} catch (RuntimeException re){
DateFormat df = DateFormat.getTimeInstance(DateFormat.LONG, loc);
String pattern = SimpleDateFormat.class.cast(df).toPattern();
fail("locale=" + loc + ", pattern=[" + pattern + "] => " + re.getMessage() + ")");
}
}
}
@Test
public void parseTime24Smart() throws ParseException {
ParseLog plog = new ParseLog();
assertThat(
ChronoFormatter.setUp(PlainTime.class, Locale.ENGLISH)
.addPattern("HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.SMART)
.parse("24:00", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(5));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => Time 24:00 not allowed"),
is(true));
}
@Test
public void parseTime24Lax() throws ParseException {
assertThat(
ChronoFormatter.setUp(PlainTime.class, Locale.ENGLISH)
.addPattern("HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.LAX)
.parse("24:00"),
is(PlainTime.midnightAtEndOfDay()));
}
@Test
public void parseTime48Lax() throws ParseException {
assertThat(
ChronoFormatter.setUp(PlainTime.class, Locale.ENGLISH)
.addPattern("HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.LAX)
.parse("48:00"),
is(PlainTime.midnightAtEndOfDay()));
}
@Test(expected=ParseException.class)
public void parseTimestampT27Smart() throws ParseException {
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ENGLISH)
.addPattern("uuuu-MM-dd HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.SMART)
.parse("2014-12-31 27:00");
}
@Test
public void parseTimestampT27Lax() throws ParseException {
assertThat(
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ENGLISH)
.addPattern("uuuu-MM-dd HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.LAX)
.parse("2014-12-31 27:00"),
is(PlainTimestamp.of(2015, 1, 1, 3, 0)));
}
@Test(expected=ParseException.class)
public void parseTimestampMonth13Smart() throws ParseException {
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ENGLISH)
.addPattern("uuuu-MM-dd HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.SMART)
.parse("2014-13-31 27:00");
}
@Test
public void parseTimestampMonth13Lax() throws ParseException {
assertThat(
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ENGLISH)
.addPattern("uuuu-MM-dd HH:mm", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.LAX)
.parse("2014-13-31 27:00"),
is(PlainTimestamp.of(2015, 2, 1, 3, 0)));
}
@Test
public void parseTimestampDefaultingEndOfDay() throws ParseException {
PlainTimestamp tsp =
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ENGLISH)
.addPattern("uuuu-MM-dd", PatternType.CLDR)
.build()
.withDefault(PlainTime.COMPONENT, PlainTime.midnightAtEndOfDay())
.parse("2014-08-20");
assertThat(tsp, is(PlainTimestamp.of(2014, 8, 21, 0, 0)));
}
@Test(expected=ParseException.class)
public void parseNoDigitsFound1() throws ParseException {
ChronoFormatter.setUp(PlainDate.class, Locale.ROOT)
.addPattern("yyyy", PatternType.CLDR).build()
.with(Attributes.LENIENCY, Leniency.LAX)
.parse("abcd");
}
@Test(expected=ParseException.class)
public void parseNoDigitsFound2() throws ParseException {
Iso8601Format.BASIC_CALENDAR_DATE.parse("0625");
}
@Test
public void parseRawData() {
ChronoFormatter<?> cf = Iso8601Format.EXTENDED_DATE_TIME_OFFSET;
ParseLog plog = new ParseLog();
String text = "2014-10-21T15:10:00+02:00";
cf.parse(text, plog);
ChronoEntity<?> e1 = plog.getRawValues();
ChronoEntity<?> e2 = cf.parseRaw(text);
assertThat(e1.equals(e2.with(Moment.axis().element(), null)), is(true));
}
@Test
public void parseRawDataHistoric() {
ChronoFormatter<?> cf = ChronoFormatter.ofDatePattern("G yyyy, MMM/d", PatternType.CLDR, Locale.ENGLISH);
ChronoHistory history = ChronoHistory.ofFirstGregorianReform();
ChronoEntity<?> e = cf.parseRaw("AD 1492, Jan/1");
assertThat(e.get(history.era()), is(HistoricEra.AD));
assertThat(e.get(history.yearOfEra()), is(1492));
assertThat(e.get(history.month()), is(1));
assertThat(e.get(history.dayOfMonth()), is(1));
assertThat(e.contains(PlainDate.DAY_OF_MONTH), is(false));
}
@Test
public void printVariableHourDecimalMinute()
throws ParseException {
ChronoFormatter<PlainTime> formatter =
ChronoFormatter
.setUp(PlainTime.class, Locale.ROOT)
.addInteger(PlainTime.ISO_HOUR, 1, 2)
.addFixedDecimal(PlainTime.DECIMAL_MINUTE, 3, 1)
.build();
assertThat(
formatter.format(PlainTime.of(17, 8, 30)),
is("1708,5"));
assertThat(
formatter.format(PlainTime.of(7, 8, 30)),
is("708,5"));
}
@Test(expected=NullPointerException.class)
public void momentFormatterWithoutTimezone1() {
Moment.formatter(DisplayMode.FULL, Locale.FRENCH, null);
}
@Test(expected=NullPointerException.class)
public void momentFormatterWithoutTimezone2() {
Moment.formatter("HH:mm:ss", PatternType.CLDR, Locale.US, null);
}
@Test(expected=IllegalArgumentException.class)
public void momentFormatterWithoutTimezoneWhenPrinting() {
ChronoFormatter<Moment> formatter =
ChronoFormatter.setUp(Moment.class, Locale.FRENCH)
.addPattern("HH:mm:ss", PatternType.CLDR)
.build();
formatter.format(Moment.UNIX_EPOCH);
}
@Test
public void momentFormatterRFC1123() {
assertThat(
Moment.formatterRFC1123().format(Moment.UNIX_EPOCH),
is("Thu, 1 Jan 1970 00:00:00 GMT"));
}
@Test
public void momentFormatterPrintingDecimalMinute() {
ChronoFormatter<Moment> formatter =
ChronoFormatter.setUp(Moment.class, Locale.US)
.addPattern("uuuu-MM-dd HH:", PatternType.CLDR)
.addFixedDecimal(PlainTime.DECIMAL_MINUTE, 3, 1)
.build()
.withTimezone(ZonalOffset.UTC);
assertThat(
formatter.format(Moment.UNIX_EPOCH),
is("1970-01-01 00:00.0"));
}
@Test
public void momentFormatterParsingDecimalMinute() throws ParseException {
ChronoFormatter<Moment> formatter =
ChronoFormatter.setUp(Moment.class, Locale.US)
.addPattern("uuuu-MM-dd HH:", PatternType.CLDR)
.addFixedDecimal(PlainTime.DECIMAL_MINUTE, 3, 1)
.build()
.withTimezone(ZonalOffset.UTC);
assertThat(
formatter.parse("1970-01-01 00:00.0"),
is(Moment.UNIX_EPOCH));
}
@Test
public void parseWallTimeWithInvalidHour() throws ParseException {
assertThat(
Iso8601Format.EXTENDED_WALL_TIME.parse("24:00:00"),
is(PlainTime.midnightAtEndOfDay()));
ParseLog plog = new ParseLog();
assertThat(
Iso8601Format.EXTENDED_WALL_TIME.parse("24:15:34", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(8));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => Time component out of range."),
is(true));
}
@Test
public void parseWallTimeWithInvalidSecond() throws ParseException {
assertThat(
Iso8601Format.EXTENDED_WALL_TIME.parse("23:59:59"),
is(PlainTime.of(23, 59, 59)));
assertThat(
Iso8601Format.EXTENDED_WALL_TIME
.with(Attributes.LENIENCY, Leniency.LAX).parse("23:59:60"),
is(PlainTime.of(24)));
ParseLog plog = new ParseLog();
assertThat(
Iso8601Format.EXTENDED_WALL_TIME.parse("23:59:60", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(8));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => Time component out of range."),
is(true));
}
@Test
public void parseIsoCalendarDateInvalidMonth() throws ParseException {
ParseLog plog = new ParseLog();
assertThat(
Iso8601Format.EXTENDED_CALENDAR_DATE.parse("2015-13-10", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(10));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => MONTH_OF_YEAR out of range: 13"),
is(true));
}
@Test
public void parseIsoCalendarDateInvalidDayOfMonth() throws ParseException {
assertThat(
Iso8601Format.EXTENDED_CALENDAR_DATE.parse("2012-02-29"),
is(PlainDate.of(2012, 2, 29)));
ParseLog plog = new ParseLog();
assertThat(
Iso8601Format.EXTENDED_CALENDAR_DATE.parse("2015-02-29", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(10));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => DAY_OF_MONTH out of range: 29"),
is(true));
}
@Test
public void parseIsoOrdinalDateInvalidDayOfYear() throws ParseException {
assertThat(
Iso8601Format.EXTENDED_ORDINAL_DATE.parse("2012-366"),
is(PlainDate.of(2012, 12, 31)));
ParseLog plog = new ParseLog();
assertThat(
Iso8601Format.EXTENDED_ORDINAL_DATE.parse("2015-366", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(8));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => DAY_OF_YEAR out of range: 366"),
is(true));
}
@Test
public void parseIsoWeekdateInvalidWeekOfYear() throws ParseException {
assertThat(
Iso8601Format.EXTENDED_WEEK_DATE.parse("2015-W53-1"),
is(PlainDate.of(2015, 12, 28)));
ParseLog plog = new ParseLog();
assertThat(
Iso8601Format.EXTENDED_WEEK_DATE.parse("2016-W53-1", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(10));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => WEEK_OF_YEAR (ISO) out of range: 53"),
is(true));
}
@Test
public void parseQuarterDateQ1Valid() throws ParseException {
assertThat(
getQuarterDateFormatter().parse("2015-Q1-90"),
is(PlainDate.of(2015, 3, 31)));
}
@Test(expected=ParseException.class)
public void parseQuarterDateQ1Invalid() throws ParseException {
getQuarterDateFormatter().parse("2015-Q1-91");
}
@Test
public void parseQuarterDateQ1LeapValid() throws ParseException {
assertThat(
getQuarterDateFormatter().parse("2012-Q1-91"),
is(PlainDate.of(2012, 3, 31)));
}
@Test(expected=ParseException.class)
public void parseQuarterDateQ1LeapInvalid() throws ParseException {
getQuarterDateFormatter().parse("2012-Q1-92");
}
@Test
public void parseQuarterDateQ2Valid() throws ParseException {
assertThat(
getQuarterDateFormatter().parse("2015-Q2-91"),
is(PlainDate.of(2015, 6, 30)));
}
@Test(expected=ParseException.class)
public void parseQuarterDateQ2Invalid() throws ParseException {
getQuarterDateFormatter().parse("2015-Q2-92");
}
@Test
public void parseQuarterDateQ3Valid() throws ParseException {
assertThat(
getQuarterDateFormatter().parse("2015-Q3-92"),
is(PlainDate.of(2015, 9, 30)));
}
@Test(expected=ParseException.class)
public void parseQuarterDateQ3Invalid() throws ParseException {
getQuarterDateFormatter().parse("2015-Q3-93");
}
@Test
public void parseQuarterDateQ4Valid() throws ParseException {
assertThat(
getQuarterDateFormatter().parse("2015-Q4-92"),
is(PlainDate.of(2015, 12, 31)));
}
@Test
public void parseQuarterDateQ4Invalid() throws ParseException {
ParseLog plog = new ParseLog();
assertThat(
getQuarterDateFormatter().parse("2015-Q4-93", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(10));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => DAY_OF_QUARTER out of range: 93"),
is(true));
}
@Test
public void parseQuarterDateBefore1() throws ParseException {
ParseLog plog = new ParseLog();
assertThat(
getQuarterDateFormatter().parse("2015-Q1-00", plog),
nullValue());
assertThat(plog.getErrorIndex(), is(10));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => DAY_OF_QUARTER out of range: 0"),
is(true));
}
@Test
public void parseTimeWithSecondOfDay() throws ParseException {
ChronoFormatter<PlainTime> formatter =
ChronoFormatter.setUp(PlainTime.class, Locale.US)
.addFixedInteger(PlainTime.SECOND_OF_DAY, 5)
.addLiteral('-')
.addFixedInteger(PlainTime.MILLI_OF_SECOND, 3)
.build();
assertThat(
formatter.parse("86399-123"),
is(PlainTime.of(23, 59, 59, 123000000)));
assertThat(
formatter.parse("86400-000"),
is(PlainTime.of(24)));
}
@Test
public void parseTimeWithNanoOfDay() throws ParseException {
ChronoFormatter<PlainTime> formatter =
ChronoFormatter.setUp(PlainTime.class, Locale.US)
.addLongNumber(
PlainTime.NANO_OF_DAY, 14, 14, SignPolicy.SHOW_NEVER)
.build();
long nanoOfDay = 86400 * 1000000000L;
ParseLog plog = new ParseLog();
assertThat(
formatter.parse(String.valueOf(nanoOfDay - 1)),
is(PlainTime.of(23, 59, 59, 999999999)));
assertThat(
formatter.parse(String.valueOf(nanoOfDay)),
is(PlainTime.of(24)));
assertThat(
formatter.parse(String.valueOf(nanoOfDay + 1), plog),
nullValue());
assertThat(plog.getErrorIndex(), is(14));
assertThat(
plog.getErrorMessage().startsWith(
"Validation failed => NANO_OF_DAY out of range:"),
is(true));
}
@Test
public void printIndividualFormat1() throws ParseException {
ChronoFormatter<Moment> formatter =
ChronoFormatter.setUp(Moment.class, Locale.US)
.startSection(Attributes.PAD_CHAR, '#')
.padNext(2)
.addPattern("M/dd/yyyy hh:mm a ", PatternType.CLDR)
.endSection()
.addLongTimezoneName(Timezone.getPreferredIDs(Locale.US, false, "DEFAULT"))
.addLiteral('/')
.addShortTimezoneName(Timezone.getPreferredIDs(Locale.US, false, "DEFAULT"))
.addLiteral('/')
.addTimezoneOffset()
.build()
.withStdTimezone();
PlainTimestamp tsp = PlainDate.of(2015, 2).atStartOfDay();
Moment moment = tsp.in(Timezone.of("America/New_York"));
ZonalOffset offset = Timezone.ofSystem().getOffset(moment);
String displayedOffset = (offset.equals(ZonalOffset.UTC) ? "Z" : offset.toString());
tsp = moment.toZonalTimestamp(offset);
String s = PlainTimestamp.formatter("MM/dd/yyyy hh:mm a ", PatternType.CLDR, Locale.US).format(tsp);
assertThat(
formatter.format(moment),
is("#" + s.substring(1)
+ Timezone.ofSystem().getDisplayName(NameStyle.LONG_STANDARD_TIME, Locale.US)
+ "/" + Timezone.ofSystem().getDisplayName(NameStyle.SHORT_STANDARD_TIME, Locale.US)
+ "/" + displayedOffset
)
);
}
@Test
public void printIndividualFormat2() throws ParseException {
ChronoFormatter<PlainDate> formatter =
ChronoFormatter.setUp(PlainDate.class, Locale.US)
.startSection(Attributes.PAD_CHAR, '#')
.addNumerical(PlainDate.MONTH_OF_YEAR, 1, 2)
.padPrevious(2)
.endSection()
.addLiteral(' ')
.addText(PlainDate.DAY_OF_WEEK, Collections.singletonMap(Weekday.THURSDAY, "Donnerstag"))
.addLiteral(" (attribute-value=")
.addLiteral(Attributes.ZERO_DIGIT)
.addLiteral(") ")
.addOrdinal(PlainDate.DAY_OF_MONTH, Collections.singletonMap(PluralCategory.OTHER, "st"))
.build()
.with(Attributes.ZERO_DIGIT, '8'); // just done here for better test coverage
assertThat(
formatter.format(PlainDate.of(2015, 1)),
is("9# Donnerstag (attribute-value=8) 9st") // "9" because of value of Attributes.ZERO_DIGIT
);
}
@Test
public void toJavaTextFormat() throws ParseException {
ChronoFormatter<Moment> formatter =
ChronoFormatter.setUp(Moment.class, Locale.US)
.addPattern("M/dd/yyyy hh:mm a ", PatternType.CLDR)
.addTimezoneOffset()
.build()
.withTimezone("America/New_York");
PlainTimestamp tsp = PlainDate.of(2015, 1, 2).atStartOfDay();
Moment moment = tsp.in(Timezone.of("America/New_York"));
FieldPosition fpos = new FieldPosition(DateFormat.Field.TIME_ZONE); //.TIMEZONE_FIELD);
assertThat(
formatter.toFormat().format(moment, new StringBuffer(), fpos).toString(),
is("1/02/2015 12:00 am -05:00")
);
assertThat(fpos.getBeginIndex(), is(19));
assertThat(fpos.getEndIndex(), is(25));
}
@Test
public void printZDT() {
Moment moment = Moment.of(1278028824, TimeScale.UTC);
Timezone tz = Timezone.of("Asia/Tokyo");
ChronoFormatter<Moment> formatter =
Iso8601Format.EXTENDED_DATE_TIME_OFFSET;
assertThat(
moment.inZonalView(tz.getID()).print(formatter),
is("2012-07-01T08:59:60+09:00"));
}
@Test
public void parseZDT() throws ParseException {
Moment moment = Moment.of(1278028824, TimeScale.UTC);
ChronoFormatter<Moment> formatter =
Iso8601Format.EXTENDED_DATE_TIME_OFFSET;
assertThat(
ZonalDateTime.parse("2012-07-01T08:59:60+09:00", formatter),
is(moment.inZonalView(ZonalOffset.ofHours(AHEAD_OF_UTC, 9))));
}
@Test(expected = ParseException.class)
public void parseAmbivalentOffset() throws ParseException {
ChronoFormatter<Moment> formatter =
ChronoFormatter.ofMomentPattern(
"uuuu-MM-dd'T'HH:mm:ssXXX'['VV']'",
PatternType.CLDR,
Locale.ROOT,
ZonalOffset.UTC
).with(Leniency.STRICT);
formatter.parse("2012-07-01T08:59:60+01:00[Asia/Tokyo]");
}
@Test(expected = ParseException.class)
public void parseOffsetWithoutSignInSmartMode() throws ParseException {
ChronoFormatter<Moment> formatter =
ChronoFormatter.ofMomentPattern(
"uuuu-MM-dd'T'HH:mm:ss XXX",
PatternType.CLDR,
Locale.ROOT,
ZonalOffset.UTC
).with(Leniency.SMART);
formatter.parse("2012-07-01T08:59:60 9:00");
}
@Test
public void parseOffsetWithoutSignInLaxMode() throws ParseException {
ChronoFormatter<Moment> formatter =
ChronoFormatter.ofMomentPattern(
"uuuu-MM-dd'T'HH:mm:ss XXX",
PatternType.CLDR,
Locale.ROOT,
ZonalOffset.UTC
).with(Leniency.LAX);
assertThat(
formatter.parse("2012-07-01T08:59:60 9:00"),
is(PlainTimestamp.of(2012, 7, 1, 0, 0).atUTC().minus(1, SI.SECONDS)));
}
@Test
public void formatPlainTimestampWithOffset() {
ChronoFormatter<PlainTimestamp> formatter =
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ROOT)
.addPattern("uuuu-MM-dd'T'HH:mmXXX", PatternType.CLDR).build();
assertThat(
formatter.withTimezone("UTC+2").format(PlainTimestamp.of(2015, 3, 29, 2, 30)),
is("2015-03-29T02:30+02:00")
);
}
@Test(expected=IllegalArgumentException.class)
public void formatPlainTimestampWithEuropeBerlin1() {
ChronoFormatter<PlainTimestamp> formatter =
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ROOT)
.addPattern("uuuu-MM-dd'T'HH:mm[VV]", PatternType.CLDR).build();
formatter.withTimezone("Europe/Berlin").format(PlainTimestamp.of(2015, 3, 29, 2, 30));
}
@Test(expected=IllegalArgumentException.class)
public void formatPlainTimestampWithEuropeBerlin2() {
ChronoFormatter<PlainTimestamp> formatter =
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ROOT)
.addPattern("uuuu-MM-dd'T'HH:mmXXX", PatternType.CLDR).build();
formatter.withTimezone("Europe/Berlin").format(PlainTimestamp.of(2015, 3, 29, 2, 30));
}
@Test(expected=IllegalArgumentException.class)
public void formatPlainTimestampWithEuropeBerlin3() {
ChronoFormatter<PlainTimestamp> formatter =
ChronoFormatter.setUp(PlainTimestamp.class, Locale.ROOT)
.addPattern("uuuu-MM-dd'T'HH:mm[z]", PatternType.CLDR).build();
formatter.withTimezone("Europe/Berlin").format(PlainTimestamp.of(2015, 3, 29, 2, 30));
}
@Test
public void iteratorOverParsedValues()
throws IOException, ClassNotFoundException {
ParseLog plog = new ParseLog();
ChronoFormatter<PlainTime> formatter = ChronoFormatter.ofTimePattern("h:mm B", PatternType.CLDR, Locale.US);
PlainTime time = formatter.parse("9:45 in the evening", plog);
assertThat(time, is(PlainTime.of(21, 45)));
Set<ChronoElement<?>> elements = plog.getRawValues().getRegisteredElements();
assertThat(elements.size(), is(4));
for (ChronoElement<?> element : elements) {
String n = element.name();
assertThat(
n.equals("CLOCK_HOUR_OF_AMPM")
|| n.equals("MINUTE_OF_HOUR")
|| n.equals("APPROXIMATE_DAY_PERIOD")
|| n.equals("AM_PM_OF_DAY"),
is(true));
}
}
@Test
public void parseZDTWithException() throws ParseException {
Timezone tz = Timezone.of("Asia/Tokyo");
TemporalFormatter<Moment> formatter =
Moment.formatter("yyyy-MM-dd HH:mmZ", PatternType.CLDR, Locale.ROOT, tz.getID());
try {
ZonalDateTime zdt = ZonalDateTime.parse("2012-07-01T09:00+0900", formatter);
fail("Parsed successfully to: " + zdt + ", but expected exception.");
} catch (ParseException pe) {
assertThat(pe.getMessage(), is("Cannot parse: \"2012-07-01T09:00+0900\" (expected: [ ], found: [T])"));
}
}
@Test
public void embeddedFormatWithHistory() throws ParseException {
ChronoFormatter<PlainDate> embedded =
ChronoFormatter.ofDatePattern("d. MMMM yyyy", PatternType.CLDR, Locale.GERMANY);
ChronoFormatter<PlainDate> f =
ChronoFormatter.setUp(PlainDate.axis(), Locale.ROOT)
.addCustomized(PlainDate.COMPONENT, embedded)
.build()
.with(ChronoHistory.ofFirstGregorianReform())
.with(Locale.ENGLISH)
.withDefault(ChronoHistory.ofFirstGregorianReform().era(), HistoricEra.AD);
assertThat(f.format(PlainDate.of(1582, 10, 14)), is("4. October 1582"));
assertThat(f.parse("4. October 1582"), is(PlainDate.of(1582, 10, 14)));
}
@Test
public void embeddedWithDefaults() throws ParseException {
ChronoFormatter<PlainDate> embedded =
ChronoFormatter.ofDatePattern("[uuuu-]MM-dd", PatternType.CLDR, Locale.ROOT);
ChronoFormatter<PlainTimestamp> f =
ChronoFormatter.setUp(PlainTimestamp.axis(), Locale.ROOT)
.addCustomized(
PlainDate.COMPONENT,
new ChronoPrinter<PlainDate>() {
@Override
public <R> R print(
PlainDate formattable,
Appendable buffer,
AttributeQuery attributes,
ChronoFunction<ChronoDisplay, R> query
) throws IOException {
return null;
}
},
embedded)
.build()
.withDefault(PlainDate.YEAR, 2016)
.withDefault(PlainTime.ISO_HOUR, 0);
PlainTimestamp tsp = f.parse("02-29");
assertThat(tsp, is(PlainTimestamp.of(2016, 2, 29, 0, 0)));
}
private static ChronoFormatter<PlainDate> getQuarterDateFormatter() {
return ChronoFormatter.setUp(PlainDate.class, Locale.US)
.addFixedInteger(PlainDate.YEAR, 4)
.addLiteral('-')
.addText(PlainDate.QUARTER_OF_YEAR)
.addLiteral('-')
.addFixedInteger(PlainDate.DAY_OF_QUARTER, 2)
.build()
.with(Attributes.TEXT_WIDTH, TextWidth.ABBREVIATED);
}
}