@Test(dataProvider = "resolve_ymaa") public void test_resolve_ymaa_smart(int y, int m, int w, int d, LocalDate expected, boolean smart, boolean strict) { Map<TemporalField, Long> fieldValues = new HashMap<>(); fieldValues.put(ChronoField.YEAR, (long) y); fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m); fieldValues.put(ChronoField.ALIGNED_WEEK_OF_MONTH, (long) w); fieldValues.put(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH, (long) d); if (smart) { LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART); assertEquals(date, expected); assertEquals(fieldValues.size(), 0); } else { try { IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART); fail("Should have failed"); } catch (DateTimeException ex) { // expected } } }
@DataProvider(name = "era_epochSecond_dataProvider") Object[][] data_era_epochSecond() { return new Object[][] { {JapaneseChronology.INSTANCE, JapaneseEra.MEIJI, 1873 - YDIFF_MEIJI, 9, 7, 1, 2, 2, OFFSET_P0100}, {JapaneseChronology.INSTANCE, JapaneseEra.SHOWA, 1928 - YDIFF_SHOWA, 2, 28, 1, 2, 2, OFFSET_M0100}, {JapaneseChronology.INSTANCE, JapaneseEra.HEISEI, 1989 - YDIFF_HEISEI, 1, 8, 1, 2, 2, OFFSET_P0100}, {HijrahChronology.INSTANCE, HijrahEra.AH, 1434, 9, 7, 1, 2, 2, OFFSET_P0100}, {MinguoChronology.INSTANCE, MinguoEra.BEFORE_ROC, 1873 - YDIFF_MINGUO, 9, 7, 1, 2, 2, OFFSET_P0100}, {MinguoChronology.INSTANCE, MinguoEra.ROC, 1928 - YDIFF_MINGUO, 2, 28, 1, 2, 2, OFFSET_M0100}, {MinguoChronology.INSTANCE, MinguoEra.ROC, 1989 - YDIFF_MINGUO, 1, 8, 1, 2, 2, OFFSET_P0100}, {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1873 + YDIFF_THAIBUDDHIST, 9, 7, 1, 2, 2, OFFSET_P0100}, {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1928 + YDIFF_THAIBUDDHIST, 2, 28, 1, 2, 2, OFFSET_M0100}, {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1989 + YDIFF_THAIBUDDHIST, 1, 8, 1, 2, 2, OFFSET_P0100}, {IsoChronology.INSTANCE, IsoEra.CE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100}, {IsoChronology.INSTANCE, IsoEra.CE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100}, {IsoChronology.INSTANCE, IsoEra.CE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100}, }; }
/** * Creates a local date from the year, month and day fields. * * @param year the year to represent, validated from MIN_YEAR to MAX_YEAR * @param month the month-of-year to represent, from 1 to 12, validated * @param dayOfMonth the day-of-month to represent, validated from 1 to 31 * @return the local date, not null * @throws DateTimeException if the day-of-month is invalid for the month-year */ private static LocalDate create(int year, int month, int dayOfMonth) { if (dayOfMonth > 28) { int dom = 31; switch (month) { case 2: dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28); break; case 4: case 6: case 9: case 11: dom = 30; break; } if (dayOfMonth > dom) { if (dayOfMonth == 29) { throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year"); } else { throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'"); } } } return new LocalDate(year, month, dayOfMonth); }
/** * Gets the text for the specified chrono, field, locale and style * for the purpose of formatting. * <p> * The text associated with the value is returned. * The null return value should be used if there is no applicable text, or * if the text would be a numeric representation of the value. * * @param chrono the Chronology to get text for, not null * @param field the field to get text for, not null * @param value the field value to get text for, not null * @param style the style to get text for, not null * @param locale the locale to get text for, not null * @return the text for the field value, null if no text found */ public String getText(Chronology chrono, TemporalField field, long value, TextStyle style, Locale locale) { if (chrono == IsoChronology.INSTANCE || !(field instanceof ChronoField)) { return getText(field, value, style, locale); } int fieldIndex; int fieldValue; if (field == ERA) { fieldIndex = Calendar.ERA; if (chrono == JapaneseChronology.INSTANCE) { if (value == -999) { fieldValue = 0; } else { fieldValue = (int) value + 2; } } else { fieldValue = (int) value; } } else if (field == MONTH_OF_YEAR) { fieldIndex = Calendar.MONTH; fieldValue = (int) value - 1; } else if (field == DAY_OF_WEEK) { fieldIndex = Calendar.DAY_OF_WEEK; fieldValue = (int) value + 1; if (fieldValue > 7) { fieldValue = Calendar.SUNDAY; } } else if (field == AMPM_OF_DAY) { fieldIndex = Calendar.AM_PM; fieldValue = (int) value; } else { return null; } return CalendarDataUtility.retrieveJavaTimeFieldValueName( chrono.getCalendarType(), fieldIndex, fieldValue, style.toCalendarStyle(), locale); }
/** * Creates a transition instance for the specified year. * <p> * Calculations are performed using the ISO-8601 chronology. * * @param year the year to create a transition for, not null * @return the transition instance, not null */ public ZoneOffsetTransition createTransition(int year) { LocalDate date; if (dom < 0) { date = LocalDate.of(year, month, month.length(IsoChronology.INSTANCE.isLeapYear(year)) + 1 + dom); if (dow != null) { date = date.with(previousOrSame(dow)); } } else { date = LocalDate.of(year, month, dom); if (dow != null) { date = date.with(nextOrSame(dow)); } } if (timeEndOfDay) { date = date.plusDays(1); } LocalDateTime localDT = LocalDateTime.of(date, time); LocalDateTime transition = timeDefinition.createDateTime(localDT, standardOffset, offsetBefore); return new ZoneOffsetTransition(transition, offsetBefore, offsetAfter); }
@Test(dataProvider = "resolve_yd") public void test_resolve_yd_smart(int y, int d, LocalDate expected, boolean smart, boolean strict) { Map<TemporalField, Long> fieldValues = new HashMap<>(); fieldValues.put(ChronoField.YEAR, (long) y); fieldValues.put(ChronoField.DAY_OF_YEAR, (long) d); if (smart) { LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART); assertEquals(date, expected); assertEquals(fieldValues.size(), 0); } else { try { IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART); fail("Should have failed"); } catch (DateTimeException ex) { // expected } } }
@Test(dataProvider = "RangeVersusCalendar") public void test_IsoChrono_vsCalendar(LocalDate isoStartDate, LocalDate isoEndDate) { GregorianCalendar cal = new GregorianCalendar(); assertEquals(cal.getCalendarType(), "gregory", "Unexpected calendar type"); LocalDate isoDate = IsoChronology.INSTANCE.date(isoStartDate); cal.setTimeZone(TimeZone.getTimeZone("GMT+00")); cal.set(Calendar.YEAR, isoDate.get(YEAR)); cal.set(Calendar.MONTH, isoDate.get(MONTH_OF_YEAR) - 1); cal.set(Calendar.DAY_OF_MONTH, isoDate.get(DAY_OF_MONTH)); while (isoDate.isBefore(isoEndDate)) { assertEquals(isoDate.get(DAY_OF_MONTH), cal.get(Calendar.DAY_OF_MONTH), "Day mismatch in " + isoDate + "; cal: " + cal); assertEquals(isoDate.get(MONTH_OF_YEAR), cal.get(Calendar.MONTH) + 1, "Month mismatch in " + isoDate); assertEquals(isoDate.get(YEAR_OF_ERA), cal.get(Calendar.YEAR), "Year mismatch in " + isoDate); isoDate = isoDate.plus(1, ChronoUnit.DAYS); cal.add(Calendar.DAY_OF_MONTH, 1); } }
@Override public boolean format(DateTimePrintContext context, StringBuilder buf) { Long value = context.getValue(field); if (value == null) { return false; } String text; Chronology chrono = context.getTemporal().query(TemporalQueries.chronology()); if (chrono == null || chrono == IsoChronology.INSTANCE) { text = provider.getText(field, value, textStyle, context.getLocale()); } else { text = provider.getText(chrono, field, value, textStyle, context.getLocale()); } if (text == null) { return numberPrinterParser().format(context, buf); } buf.append(text); return true; }
@Test(dataProvider = "resolve_ymd") public void test_resolve_ymd_strict(int y, int m, int d, LocalDate expected, Object smart, boolean strict) { Map<TemporalField, Long> fieldValues = new HashMap<>(); fieldValues.put(ChronoField.YEAR, (long) y); fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m); fieldValues.put(ChronoField.DAY_OF_MONTH, (long) d); if (strict) { LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT); assertEquals(date, expected); assertEquals(fieldValues.size(), 0); } else { try { IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT); fail("Should have failed"); } catch (DateTimeException ex) { // expected } } }
@Test(dataProvider = "resolve_yearOfEra") public void test_resolve_yearOfEra(ResolverStyle style, Integer e, Integer yoe, Integer y, ChronoField field, Integer expected) { Map<TemporalField, Long> fieldValues = new HashMap<>(); if (e != null) { fieldValues.put(ChronoField.ERA, (long) e); } if (yoe != null) { fieldValues.put(ChronoField.YEAR_OF_ERA, (long) yoe); } if (y != null) { fieldValues.put(ChronoField.YEAR, (long) y); } if (field != null) { LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, style); assertEquals(date, null); assertEquals(fieldValues.get(field), (Long) expected.longValue()); assertEquals(fieldValues.size(), 1); } else { try { IsoChronology.INSTANCE.resolveDate(fieldValues, style); fail("Should have failed"); } catch (DateTimeException ex) { // expected } } }
@DataProvider(name = "invalidSerialformClasses") Object[][] invalid_serial_classes() { return new Object[][]{ {IsoChronology.class}, {JapaneseChronology.class}, {MinguoChronology.class}, {ThaiBuddhistChronology.class}, {HijrahChronology.class}, }; }
@Test(dataProvider = "resolve_ymd") public void test_resolve_ymd_lenient(int y, int m, int d, LocalDate expected, Object smart, boolean strict) { Map<TemporalField, Long> fieldValues = new HashMap<>(); fieldValues.put(ChronoField.YEAR, (long) y); fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m); fieldValues.put(ChronoField.DAY_OF_MONTH, (long) d); LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.LENIENT); assertEquals(date, expected); assertEquals(fieldValues.size(), 0); }
@DataProvider(name="query") Object[][] data_query() { return new Object[][] { {TEST_2007_07_15, TemporalQueries.chronology(), IsoChronology.INSTANCE}, {TEST_2007_07_15, TemporalQueries.zoneId(), null}, {TEST_2007_07_15, TemporalQueries.precision(), ChronoUnit.DAYS}, {TEST_2007_07_15, TemporalQueries.zone(), null}, {TEST_2007_07_15, TemporalQueries.offset(), null}, {TEST_2007_07_15, TemporalQueries.localDate(), TEST_2007_07_15}, {TEST_2007_07_15, TemporalQueries.localTime(), null}, }; }
/** * Obtains an instance of {@code Period} from a temporal amount. * <p> * This obtains a period based on the specified amount. * A {@code TemporalAmount} represents an amount of time, which may be * date-based or time-based, which this factory extracts to a {@code Period}. * <p> * The conversion loops around the set of units from the amount and uses * the {@link ChronoUnit#YEARS YEARS}, {@link ChronoUnit#MONTHS MONTHS} * and {@link ChronoUnit#DAYS DAYS} units to create a period. * If any other units are found then an exception is thrown. * <p> * If the amount is a {@code ChronoPeriod} then it must use the ISO chronology. * * @param amount the temporal amount to convert, not null * @return the equivalent period, not null * @throws DateTimeException if unable to convert to a {@code Period} * @throws ArithmeticException if the amount of years, months or days exceeds an int */ public static Period from(TemporalAmount amount) { if (amount instanceof Period) { return (Period) amount; } if (amount instanceof ChronoPeriod) { if (IsoChronology.INSTANCE.equals(((ChronoPeriod) amount).getChronology()) == false) { throw new DateTimeException("Period requires ISO chronology: " + amount); } } Objects.requireNonNull(amount, "amount"); int years = 0; int months = 0; int days = 0; for (TemporalUnit unit : amount.getUnits()) { long unitAmount = amount.get(unit); if (unit == ChronoUnit.YEARS) { years = Math.toIntExact(unitAmount); } else if (unit == ChronoUnit.MONTHS) { months = Math.toIntExact(unitAmount); } else if (unit == ChronoUnit.DAYS) { days = Math.toIntExact(unitAmount); } else { throw new DateTimeException("Unit must be Years, Months or Days, but was " + unit); } } return create(years, months, days); }
/** * Validates that the temporal has the correct chronology. */ private void validateChrono(TemporalAccessor temporal) { Objects.requireNonNull(temporal, "temporal"); Chronology temporalChrono = temporal.query(TemporalQueries.chronology()); if (temporalChrono != null && IsoChronology.INSTANCE.equals(temporalChrono) == false) { throw new DateTimeException("Chronology mismatch, expected: ISO, actual: " + temporalChrono.getId()); } }
@DataProvider(name = "calendars") Chronology[][] data_of_calendars() { return new Chronology[][]{ {HijrahChronology.INSTANCE}, {IsoChronology.INSTANCE}, {JapaneseChronology.INSTANCE}, {MinguoChronology.INSTANCE}, {ThaiBuddhistChronology.INSTANCE}}; }
/** * Resolves the date, resolving days past the end of month. * * @param year the year to represent, validated from MIN_YEAR to MAX_YEAR * @param month the month-of-year to represent, validated from 1 to 12 * @param day the day-of-month to represent, validated from 1 to 31 * @return the resolved date, not null */ private static LocalDate resolvePreviousValid(int year, int month, int day) { switch (month) { case 2: day = Math.min(day, IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28); break; case 4: case 6: case 9: case 11: day = Math.min(day, 30); break; } return new LocalDate(year, month, day); }
@DataProvider(name = "calendars") Chronology[][] data_of_calendars() { return new Chronology[][]{ {HijrahChronology.INSTANCE}, {IsoChronology.INSTANCE}, {JapaneseChronology.INSTANCE}, {MinguoChronology.INSTANCE}, {ThaiBuddhistChronology.INSTANCE}, }; }
/** * Gets the effective chronology during parsing. * * @return the effective parsing chronology, not null */ Chronology getEffectiveChronology() { Chronology chrono = currentParsed().chrono; if (chrono == null) { chrono = formatter.getChronology(); if (chrono == null) { chrono = IsoChronology.INSTANCE; } } return chrono; }
@Test public void test_withChronology_noOverride() { DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter(); TemporalAccessor accessor = f.parse(""); assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3)); assertEquals(accessor.query(TemporalQueries.localTime()), null); assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE); }
@Test(dataProvider = "resolve_yd") public void test_resolve_yd_lenient(int y, int d, LocalDate expected, boolean smart, boolean strict) { Map<TemporalField, Long> fieldValues = new HashMap<>(); fieldValues.put(ChronoField.YEAR, (long) y); fieldValues.put(ChronoField.DAY_OF_YEAR, (long) d); LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.LENIENT); assertEquals(date, expected); assertEquals(fieldValues.size(), 0); }
@Override public long getFrom(TemporalAccessor temporal) { if (isSupportedBy(temporal) == false) { throw new UnsupportedTemporalTypeException("Unsupported field: DayOfQuarter"); } int doy = temporal.get(DAY_OF_YEAR); int moy = temporal.get(MONTH_OF_YEAR); long year = temporal.getLong(YEAR); return doy - QUARTER_DAYS[((moy - 1) / 3) + (IsoChronology.INSTANCE.isLeapYear(year) ? 4 : 0)]; }
@DataProvider(name="toString") Object[][] data_toString() { return new Object[][] { {IsoChronology.INSTANCE.date(1, 1, 1), "0001-01-01"}, {IsoChronology.INSTANCE.date(1728, 10, 28), "1728-10-28"}, {IsoChronology.INSTANCE.date(1728, 10, 29), "1728-10-29"}, {IsoChronology.INSTANCE.date(1727, 12, 5), "1727-12-05"}, {IsoChronology.INSTANCE.date(1727, 12, 6), "1727-12-06"}, }; }
@DataProvider(name="query") Object[][] data_query() { return new Object[][] { {TEST_07_15, TemporalQueries.chronology(), IsoChronology.INSTANCE}, {TEST_07_15, TemporalQueries.zoneId(), null}, {TEST_07_15, TemporalQueries.precision(), null}, {TEST_07_15, TemporalQueries.zone(), null}, {TEST_07_15, TemporalQueries.offset(), null}, {TEST_07_15, TemporalQueries.localDate(), null}, {TEST_07_15, TemporalQueries.localTime(), null}, }; }
@DataProvider(name = "calendarsystemtype") Object[][] data_CalendarType() { return new Object[][] { {HijrahChronology.INSTANCE, "islamic-umalqura"}, {IsoChronology.INSTANCE, "iso8601"}, {JapaneseChronology.INSTANCE, "japanese"}, {MinguoChronology.INSTANCE, "roc"}, {ThaiBuddhistChronology.INSTANCE, "buddhist"}, }; }
@Override public int parse(DateTimeParseContext context, CharSequence parseText, int position) { int length = parseText.length(); if (position < 0 || position > length) { throw new IndexOutOfBoundsException(); } TextStyle style = (context.isStrict() ? textStyle : null); Chronology chrono = context.getEffectiveChronology(); Iterator<Entry<String, Long>> it; if (chrono == null || chrono == IsoChronology.INSTANCE) { it = provider.getTextIterator(field, style, context.getLocale()); } else { it = provider.getTextIterator(chrono, field, style, context.getLocale()); } if (it != null) { while (it.hasNext()) { Entry<String, Long> entry = it.next(); String itText = entry.getKey(); if (context.subSequenceEquals(itText, 0, parseText, position, itText.length())) { return context.setParsedField(field, entry.getValue(), position, position + itText.length()); } } if (context.isStrict()) { return ~position; } } return numberPrinterParser().parse(context, parseText, position); }
@Test public void test_epochSecond_2() { assertEquals(IsoChronology.INSTANCE.epochSecond(2008, 3, 3, 1, 2, 2, OFFSET_P0100), ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond()); assertEquals(IsoChronology.INSTANCE.epochSecond(1969, 3, 3, 1, 2, 2, OFFSET_P0100), ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond()); }
@DataProvider(name="query") Object[][] data_query() { return new Object[][] { {TEST_2008_06, TemporalQueries.chronology(), IsoChronology.INSTANCE}, {TEST_2008_06, TemporalQueries.zoneId(), null}, {TEST_2008_06, TemporalQueries.precision(), ChronoUnit.MONTHS}, {TEST_2008_06, TemporalQueries.zone(), null}, {TEST_2008_06, TemporalQueries.offset(), null}, {TEST_2008_06, TemporalQueries.localDate(), null}, {TEST_2008_06, TemporalQueries.localTime(), null}, }; }
@Test public void test_era_epochSecond_2() { assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100), ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond()); assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_P0100), ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond()); }
@DataProvider(name="query") Object[][] data_query() { return new Object[][] { {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.chronology(), IsoChronology.INSTANCE}, {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.zoneId(), null}, {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.precision(), ChronoUnit.NANOS}, {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.zone(), null}, {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.offset(), null}, {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.localDate(), LocalDate.of(2007, 7, 15)}, {TEST_2007_07_15_12_30_40_987654321, TemporalQueries.localTime(), LocalTime.of(12, 30, 40, 987654321)}, }; }
@Test public void test_chrono_byName() { Chronology c = IsoChronology.INSTANCE; Chronology test = Chronology.of("ISO"); Assert.assertNotNull(test, "The ISO calendar could not be found byName"); Assert.assertEquals(test.getId(), "ISO", "ID mismatch"); Assert.assertEquals(test.getCalendarType(), "iso8601", "Type mismatch"); Assert.assertEquals(test, c); }
@Test(dataProvider = "resolve_ymaa") public void test_resolve_ymaa_lenient(int y, int m, int w, int d, LocalDate expected, boolean smart, boolean strict) { Map<TemporalField, Long> fieldValues = new HashMap<>(); fieldValues.put(ChronoField.YEAR, (long) y); fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m); fieldValues.put(ChronoField.ALIGNED_WEEK_OF_MONTH, (long) w); fieldValues.put(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH, (long) d); LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.LENIENT); assertEquals(date, expected); assertEquals(fieldValues.size(), 0); }