@Override public Instant plus(long amountToAdd, PeriodUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { case NANOS: return plusNanos(amountToAdd); case MICROS: return plus(amountToAdd / 1000000, (amountToAdd % 1000000) * 1000); case MILLIS: return plusMillis(amountToAdd); case SECONDS: return plusSeconds(amountToAdd); case MINUTES: return plusSeconds(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_MINUTE)); case HOURS: return plusSeconds(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_HOUR)); case HALF_DAYS: return plusSeconds(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_DAY / 2)); case DAYS: return plusSeconds(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_DAY)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } return unit.doPlus(this, amountToAdd); }
/** * Obtains a {@code Period} consisting of the number of years, months, and days between two dates. * <p> * The start date is included, but the end date is not. The period is calculated by removing complete * months, then calculating the remaining number of days, adjusting to ensure that both have the same sign. * The number of months is then split into years and months based on a 12 month year. A month is considered * if the end day-of-month is greater than or equal to the start day-of-month. For example, from * {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days. * <p> * The result of this method can be a negative period if the end is before the start. The negative sign will * be the same in each of year, month and day. * * @param startDate the start date, inclusive, not null * @param endDate the end date, exclusive, not null * @return the period between the dates, not null * @throws ArithmeticException if numeric overflow occurs */ public static Period betweenISO(LocalDate startDate, LocalDate endDate) { long startMonth = startDate.getLong(EPOCH_MONTH); long endMonth = endDate.getLong(EPOCH_MONTH); long totalMonths = endMonth - startMonth; // safe int days = endDate.getDayOfMonth() - startDate.getDayOfMonth(); if (totalMonths > 0 && days < 0) { totalMonths--; LocalDate calcDate = startDate.plusMonths(totalMonths); days = (int) (endDate.toEpochDay() - calcDate.toEpochDay()); // safe } else if (totalMonths < 0 && days > 0) { totalMonths++; days -= endDate.lengthOfMonth(); } long years = totalMonths / 12; // safe int months = (int) (totalMonths % 12); // safe return ofDate(Jdk8Methods.safeToInt(years), months, days); }
/** * Returns a copy of this period with the days and hours normalized using a 24 hour day. * <p> * This normalizes the days and hours units, leaving years and months unchanged. The hours unit is adjusted * to have an absolute value less than 23, with the days unit being adjusted to compensate. For example, a * period of {@code P1DT27H} will be normalized to {@code P2DT3H}. * <p> * The sign of the days and hours units will be the same after normalization. For example, a period of * {@code P1DT-51H} will be normalized to {@code P-1DT-3H}. Since all time units are always normalized, if * the hours units changes sign then other time units will also be affected. * <p> * This instance is immutable and unaffected by this method call. * * @return a {@code Period} based on this period with excess hours normalized to days, not null * @throws ArithmeticException if numeric overflow occurs */ public Period normalizedHoursToDays() { // logic uses if statements to normalize signs to avoid unnecessary overflows long totalDays = (this.nanos / NANOS_PER_DAY) + this.days; // no overflow long splitNanos = this.nanos % NANOS_PER_DAY; if (totalDays > 0 && splitNanos < 0) { splitNanos += NANOS_PER_DAY; totalDays--; } else if (totalDays < 0 && splitNanos > 0) { splitNanos -= NANOS_PER_DAY; totalDays++; } if (totalDays == this.days && splitNanos == this.nanos) { return this; } return create(this.years, this.months, Jdk8Methods.safeToInt(totalDays), splitNanos); }
/** * Returns a copy of this {@code LocalDateTime} with the specified period added. * <p> * This instance is immutable and unaffected by this method call. * * @param newDate the new date to base the calculation on, not null * @param hours the hours to add, may be negative * @param minutes the minutes to add, may be negative * @param seconds the seconds to add, may be negative * @param nanos the nanos to add, may be negative * @param sign the sign to determine add or subtract * @return the combined result, not null */ private LocalDateTime plusWithOverflow(LocalDate newDate, long hours, long minutes, long seconds, long nanos, int sign) { // 9223372036854775808 long, 2147483648 int if ((hours | minutes | seconds | nanos) == 0) { return with(newDate, this.time); } long totDays = nanos / NANOS_PER_DAY + // max/24*60*60*1B seconds / SECONDS_PER_DAY + // max/24*60*60 minutes / MINUTES_PER_DAY + // max/24*60 hours / HOURS_PER_DAY; // max/24 totDays *= sign; // total max*0.4237... long totNanos = nanos % NANOS_PER_DAY + // max 86400000000000 (seconds % SECONDS_PER_DAY) * NANOS_PER_SECOND + // max 86400000000000 (minutes % MINUTES_PER_DAY) * NANOS_PER_MINUTE + // max 86400000000000 (hours % HOURS_PER_DAY) * NANOS_PER_HOUR; // max 86400000000000 long curNoD = this.time.toNanoOfDay(); // max 86400000000000 totNanos = totNanos * sign + curNoD; // total 432000000000000 totDays += Jdk8Methods.floorDiv(totNanos, NANOS_PER_DAY); long newNoD = Jdk8Methods.floorMod(totNanos, NANOS_PER_DAY); LocalTime newTime = (newNoD == curNoD ? this.time : LocalTime.ofNanoOfDay(newNoD)); return with(newDate.plusDays(totDays), newTime); }
private ChronoDateTimeImpl<C> plusWithOverflow(ChronoLocalDate<C> newDate, long hours, long minutes, long seconds, long nanos) { // 9223372036854775808 long, 2147483648 int if ((hours | minutes | seconds | nanos) == 0) { return with(newDate, this.time); } long totDays = nanos / NANOS_PER_DAY + // max/24*60*60*1B seconds / SECONDS_PER_DAY + // max/24*60*60 minutes / MINUTES_PER_DAY + // max/24*60 hours / HOURS_PER_DAY; // max/24 long totNanos = nanos % NANOS_PER_DAY + // max 86400000000000 (seconds % SECONDS_PER_DAY) * NANOS_PER_SECOND + // max 86400000000000 (minutes % MINUTES_PER_DAY) * NANOS_PER_MINUTE + // max 86400000000000 (hours % HOURS_PER_DAY) * NANOS_PER_HOUR; // max 86400000000000 long curNoD = this.time.toNanoOfDay(); // max 86400000000000 totNanos = totNanos + curNoD; // total 432000000000000 totDays += Jdk8Methods.floorDiv(totNanos, NANOS_PER_DAY); long newNoD = Jdk8Methods.floorMod(totNanos, NANOS_PER_DAY); LocalTime newTime = (newNoD == curNoD ? this.time : LocalTime.ofNanoOfDay(newNoD)); return with(newDate.plus(totDays, ChronoUnit.DAYS), newTime); }
@Override public Year plus(long amountToAdd, PeriodUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { case YEARS: return plusYears(amountToAdd); case DECADES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 10)); case CENTURIES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 100)); case MILLENNIA: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 1000)); case ERAS: return with(ERA, Jdk8Methods.safeAdd(getLong(ERA), amountToAdd)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } return unit.doPlus(this, amountToAdd); }
/** * Returns a copy of this duration with the specified duration added. * <p> * The duration amount is measured in terms of the specified unit. * Only a subset of units are accepted by this method. * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception. * <p> * This instance is immutable and unaffected by this method call. * * @param amountToAdd the amount of the period, measured in terms of the unit, positive or negative * @param unit the unit that the period is measured in, must have an exact duration, not null * @return a {@code Duration} based on this duration with the specified duration added, not null * @throws ArithmeticException if numeric overflow occurs */ public Duration plus(long amountToAdd, TemporalUnit unit) { Jdk8Methods.requireNonNull(unit, "unit"); if (unit == DAYS) { return plus(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_DAY), 0); } if (unit.isDurationEstimated()) { throw new DateTimeException("Unit must not have an estimated duration"); } if (amountToAdd == 0) { return this; } if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { case NANOS: return plusNanos(amountToAdd); case MICROS: return plusSeconds((amountToAdd / (1000000L * 1000)) * 1000).plusNanos((amountToAdd % (1000000L * 1000)) * 1000); case MILLIS: return plusMillis(amountToAdd); case SECONDS: return plusSeconds(amountToAdd); } return plusSeconds(Jdk8Methods.safeMultiply(unit.getDuration().seconds, amountToAdd)); } Duration duration = unit.getDuration().multipliedBy(amountToAdd); return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano()); }
/** * Obtains an instance of {@code ZoneId} from an identifier. * * @param zoneId the time-zone ID, not null * @param checkAvailable whether to check if the zone ID is available * @return the zone ID, not null * @throws DateTimeException if the ID format is invalid * @throws DateTimeException if checking availability and the ID cannot be found */ static ZoneRegion ofId(String zoneId, boolean checkAvailable) { Jdk8Methods.requireNonNull(zoneId, "zoneId"); if (zoneId.length() < 2 || PATTERN.matcher(zoneId).matches() == false) { throw new DateTimeException("Invalid ID for region-based ZoneId, invalid format: " + zoneId); } ZoneRules rules = null; try { // always attempt load for better behavior after deserialization rules = ZoneRulesProvider.getRules(zoneId, true); } catch (ZoneRulesException ex) { // special case as removed from data file if (zoneId.equals("GMT0")) { rules = ZoneOffset.UTC.getRules(); } else if (checkAvailable) { throw ex; } } return new ZoneRegion(zoneId, rules); }
@Override public HijrahDate plusMonths(long months) { if (months == 0) { return this; } int newMonth = this.monthOfYear - 1; newMonth = newMonth + (int) months; int years = newMonth / 12; newMonth = newMonth % 12; while (newMonth < 0) { newMonth += 12; years = Jdk8Methods.safeSubtract(years, 1); } int newYear = Jdk8Methods.safeAdd(this.yearOfEra, years); return HijrahDate.of(this.era, newYear, newMonth + 1, this.dayOfMonth); }
private int localizedWOWBY(TemporalAccessor temporal) { int sow = weekDef.getFirstDayOfWeek().getValue(); int isoDow = temporal.get(DAY_OF_WEEK); int dow = Jdk8Methods.floorMod(isoDow - sow, 7) + 1; long woy = localizedWeekOfYear(temporal, dow); if (woy == 0) { ChronoLocalDate previous = Chronology.from(temporal).date(temporal).minus(1, ChronoUnit.WEEKS); return (int) localizedWeekOfYear(previous, dow) + 1; } else if (woy >= 53) { int offset = startOfWeekOffset(temporal.get(DAY_OF_YEAR), dow); int year = temporal.get(YEAR); int yearLen = Year.isLeap(year) ? 366 : 365; int weekIndexOfFirstWeekNextYear = computeWeek(offset, yearLen + weekDef.getMinimalDaysInFirstWeek()); if (woy >= weekIndexOfFirstWeekNextYear) { return (int) (woy - (weekIndexOfFirstWeekNextYear - 1)); } } return (int) woy; }
/** * Obtains an instance of {@code ZonedDateTime} strictly validating the * combination of local date-time, offset and zone ID. * <p> * This creates a zoned date-time ensuring that the offset is valid for the * local date-time according to the rules of the specified zone. * If the offset is invalid, an exception is thrown. * * @param localDateTime the local date-time, not null * @param offset the zone offset, not null * @param zone the time-zone, not null * @return the zoned date-time, not null */ public static ZonedDateTime ofStrict(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) { Jdk8Methods.requireNonNull(localDateTime, "localDateTime"); Jdk8Methods.requireNonNull(offset, "offset"); Jdk8Methods.requireNonNull(zone, "zone"); ZoneRules rules = zone.getRules(); if (rules.isValidOffset(localDateTime, offset) == false) { ZoneOffsetTransition trans = rules.getTransition(localDateTime); if (trans != null && trans.isGap()) { // error message says daylight savings for simplicity // even though there are other kinds of gaps throw new DateTimeException("LocalDateTime '" + localDateTime + "' does not exist in zone '" + zone + "' due to a gap in the local time-line, typically caused by daylight savings"); } throw new DateTimeException("ZoneOffset '" + offset + "' is not valid for LocalDateTime '" + localDateTime + "' in zone '" + zone + "'"); } return new ZonedDateTime(localDateTime, offset, zone); }
@Override public YearMonth plus(long amountToAdd, PeriodUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { case MONTHS: return plusMonths(amountToAdd); case QUARTER_YEARS: return plusYears(amountToAdd / 256).plusMonths((amountToAdd % 256) * 3); // no overflow (256 is // multiple of 4) case HALF_YEARS: return plusYears(amountToAdd / 256).plusMonths((amountToAdd % 256) * 6); // no overflow (256 is // multiple of 2) case YEARS: return plusYears(amountToAdd); case DECADES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 10)); case CENTURIES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 100)); case MILLENNIA: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 1000)); case ERAS: return with(ERA, Jdk8Methods.safeAdd(getLong(ERA), amountToAdd)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } return unit.doPlus(this, amountToAdd); }
/** * Returns a copy of this year-month with the specified period in months added. * <p> * This instance is immutable and unaffected by this method call. * * @param monthsToAdd the months to add, may be negative * @return a {@code YearMonth} based on this year-month with the months added, not null * @throws DateTimeException if the result exceeds the supported range */ public YearMonth plusMonths(long monthsToAdd) { if (monthsToAdd == 0) { return this; } long monthCount = this.year * 12L + (this.month - 1); long calcMonths = monthCount + monthsToAdd; // safe overflow int newYear = YEAR.checkValidIntValue(Jdk8Methods.floorDiv(calcMonths, 12)); int newMonth = Jdk8Methods.floorMod(calcMonths, 12) + 1; return with(newYear, newMonth); }
/** * Returns a copy of this instant with the specified duration added. * <p> * This instance is immutable and unaffected by this method call. * * @param secondsToAdd the seconds to add, positive or negative * @param nanosToAdd the nanos to add, positive or negative * @return an {@code Instant} based on this instant with the specified seconds added, not null * @throws ArithmeticException if the calculation exceeds the supported range */ private Instant plus(long secondsToAdd, long nanosToAdd) { if ((secondsToAdd | nanosToAdd) == 0) { return this; } long epochSec = Jdk8Methods.safeAdd(this.seconds, secondsToAdd); epochSec = Jdk8Methods.safeAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); nanosToAdd = nanosToAdd % NANOS_PER_SECOND; long nanoAdjustment = this.nanos + nanosToAdd; // safe int+NANOS_PER_SECOND return ofEpochSecond(epochSec, nanoAdjustment); }
@Override public long periodUntil(DateTime endDateTime, PeriodUnit unit) { if (endDateTime instanceof Instant == false) { throw new DateTimeException("Unable to calculate period between objects of two different types"); } Instant end = (Instant) endDateTime; if (unit instanceof ChronoUnit) { ChronoUnit f = (ChronoUnit) unit; switch (f) { case NANOS: return nanosUntil(end); case MICROS: return nanosUntil(end) / 1000; case MILLIS: return Jdk8Methods.safeSubtract(end.toEpochMilli(), toEpochMilli()); case SECONDS: return secondsUntil(end); case MINUTES: return secondsUntil(end) / SECONDS_PER_MINUTE; case HOURS: return secondsUntil(end) / SECONDS_PER_HOUR; case HALF_DAYS: return secondsUntil(end) / (12 * SECONDS_PER_HOUR); case DAYS: return secondsUntil(end) / (SECONDS_PER_DAY); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } return unit.between(this, endDateTime).getAmount(); }
/** * Returns a copy of this period with the specified period added. * <p> * The specified unit must be one of the supported units from {@link ChronoUnit}, {@code YEARS}, * {@code MONTHS} or {@code DAYS} or be a time unit with an {@link PeriodUnit#isDurationEstimated() exact * duration}. Other units throw an exception. * <p> * This instance is immutable and unaffected by this method call. * * @param amount the amount to add, positive or negative * @param unit the unit that the amount is expressed in, not null * @return a {@code Period} based on this period with the requested amount added, not null * @throws ArithmeticException if numeric overflow occurs */ public Period plus(long amount, PeriodUnit unit) { Jdk7Methods.Objects_requireNonNull(unit, "unit"); if (unit instanceof ChronoUnit) { if (unit == YEARS || unit == MONTHS || unit == DAYS || unit.isDurationEstimated() == false) { if (amount == 0) { return this; } switch ((ChronoUnit) unit) { case NANOS: return plusNanos(amount); case MICROS: return plusNanos(Jdk8Methods.safeMultiply(amount, 1000L)); case MILLIS: return plusNanos(Jdk8Methods.safeMultiply(amount, 1000000L)); case SECONDS: return plusSeconds(amount); case MINUTES: return plusMinutes(amount); case HOURS: return plusHours(amount); case HALF_DAYS: return plusNanos(Jdk8Methods.safeMultiply(amount, 12 * NANOS_PER_HOUR)); case DAYS: return plusDays(amount); case MONTHS: return plusMonths(amount); case YEARS: return plusYears(amount); default : throw new DateTimeException("Unsupported unit: " + unit.getName()); } } } if (unit.isDurationEstimated()) { throw new DateTimeException("Unsupported unit: " + unit.getName()); } return plusNanos(Duration.of(amount, unit).toNanos()); }
/** * Returns a copy of this duration with the specified duration added. * <p> * The duration amount is measured in terms of the specified unit. Only a subset of units are accepted by * this method. The unit must either have an {@link PeriodUnit#isDurationEstimated() exact duration} or be * {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception. * <p> * This instance is immutable and unaffected by this method call. * * @param amountToAdd the amount of the period, measured in terms of the unit, positive or negative * @param unit the unit that the period is measured in, must have an exact duration, not null * @return a {@code Duration} based on this duration with the specified duration added, not null * @throws ArithmeticException if numeric overflow occurs */ public Duration plus(long amountToAdd, PeriodUnit unit) { Jdk7Methods.Objects_requireNonNull(unit, "unit"); if (unit == DAYS) { return plus(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_DAY), 0); } if (unit.isDurationEstimated()) { throw new DateTimeException("Unit must not have an estimated duration"); } if (amountToAdd == 0) { return this; } if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { case NANOS: return plusNanos(amountToAdd); case MICROS: return plusSeconds((amountToAdd / (1000000L * 1000)) * 1000).plusNanos( (amountToAdd % (1000000L * 1000)) * 1000); case MILLIS: return plusMillis(amountToAdd); case SECONDS: return plusSeconds(amountToAdd); } return plusSeconds(Jdk8Methods.safeMultiply(unit.getDuration().seconds, amountToAdd)); } Duration duration = unit.getDuration().multipliedBy(amountToAdd); return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano()); }
/** * Returns a copy of this duration with the specified duration added. * <p> * This instance is immutable and unaffected by this method call. * * @param secondsToAdd the seconds to add, positive or negative * @param nanosToAdd the nanos to add, positive or negative * @return a {@code Duration} based on this duration with the specified seconds added, not null * @throws ArithmeticException if numeric overflow occurs */ private Duration plus(long secondsToAdd, long nanosToAdd) { if ((secondsToAdd | nanosToAdd) == 0) { return this; } long epochSec = Jdk8Methods.safeAdd(this.seconds, secondsToAdd); epochSec = Jdk8Methods.safeAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); nanosToAdd = nanosToAdd % NANOS_PER_SECOND; long nanoAdjustment = this.nanos + nanosToAdd; // safe int+NANOS_PER_SECOND return ofSeconds(epochSec, nanoAdjustment); }
/** * Returns a copy of this date with the specified period added. * <p> * This method returns a new date based on this date with the specified period added. This can be used to * add any period that is defined by a unit, for example to add years, months or days. The unit is * responsible for the details of the calculation, including the resolution of any edge cases in the * calculation. * <p> * This instance is immutable and unaffected by this method call. * * @param amountToAdd the amount of the unit to add to the result, may be negative * @param unit the unit of the period to add, not null * @return a {@code LocalDate} based on this date with the specified period added, not null * @throws DateTimeException if the unit cannot be added to this type */ @Override public LocalDate plus(long amountToAdd, PeriodUnit unit) { if (unit instanceof ChronoUnit) { ChronoUnit f = (ChronoUnit) unit; switch (f) { case DAYS: return plusDays(amountToAdd); case WEEKS: return plusWeeks(amountToAdd); case MONTHS: return plusMonths(amountToAdd); case QUARTER_YEARS: return plusYears(amountToAdd / 256).plusMonths((amountToAdd % 256) * 3); // no overflow (256 is // multiple of 4) case HALF_YEARS: return plusYears(amountToAdd / 256).plusMonths((amountToAdd % 256) * 6); // no overflow (256 is // multiple of 2) case YEARS: return plusYears(amountToAdd); case DECADES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 10)); case CENTURIES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 100)); case MILLENNIA: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 1000)); case ERAS: return with(ERA, Jdk8Methods.safeAdd(getLong(ERA), amountToAdd)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } return unit.doPlus(this, amountToAdd); }
/** * Returns an offset to align week start with a day of month or day of year. * * @param day the day; 1 through infinity * @param dow the day of the week of that day; 1 through 7 * @param minDays the minimum number of days required the first week * @return an offset in days to align a day with the start of a the first 'full' week */ private int startOfWeekOffset(int day, int dow) { // offset of first day corresponding to the day of week in first 7 days (zero origin) int weekStart = Jdk8Methods.floorMod(day - dow, 7); int offset = -weekStart; if (weekStart + 1 > this.weekDef.getMinimalDaysInFirstWeek()) { // The previous week has the minimum days in the current month to be a 'week' offset = 7 - weekStart; } offset += 7; return offset; }
/** * Obtains an instance of {@code OffsetDate} from an {@code Instant} and zone ID. * <p> * This creates an offset date with the same instant as midnight at the start of day of the instant * specified. Finding the offset from UTC/Greenwich is simple as there is only one valid offset for each * instant. * * @param instant the instant to create the time from, not null * @param zone the time-zone, which may be an offset, not null * @return the offset time, not null */ public static OffsetDate ofInstant(Instant instant, ZoneId zone) { Jdk7Methods.Objects_requireNonNull(instant, "instant"); Jdk7Methods.Objects_requireNonNull(zone, "zone"); ZoneRules rules = zone.getRules(); ZoneOffset offset = rules.getOffset(instant); long epochSec = instant.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later long epochDay = Jdk8Methods.floorDiv(epochSec, SECONDS_PER_DAY); LocalDate date = LocalDate.ofEpochDay(epochDay); return new OffsetDate(date, offset); }
@Override public long periodUntil(DateTime endDateTime, PeriodUnit unit) { if (endDateTime instanceof OffsetDate == false) { throw new DateTimeException("Unable to calculate period between objects of two different types"); } if (unit instanceof ChronoUnit) { OffsetDate end = (OffsetDate) endDateTime; long offsetDiff = end.offset.getTotalSeconds() - this.offset.getTotalSeconds(); LocalDate endLocal = end.date.plusDays(Jdk8Methods.floorDiv(-offsetDiff, SECONDS_PER_DAY)); return this.date.periodUntil(endLocal, unit); } return unit.between(this, endDateTime).getAmount(); }
/** * Adds a multi-year transition rule to the current window. * <p> * This adds a rule such that the offset, expressed as a daylight savings amount, * changes at the specified date-time for each year in the range. * * @param startYear the start year of the rule, from MIN_VALUE to MAX_VALUE * @param endYear the end year of the rule, from MIN_VALUE to MAX_VALUE * @param month the month of the transition, not null * @param dayOfMonthIndicator the day-of-month of the transition, adjusted by dayOfWeek, * from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month * @param dayOfWeek the day-of-week to adjust to, null if day-of-month should not be adjusted * @param time the time that the transition occurs as defined by timeDefintion, not null * @param timeEndOfDay whether midnight is at the end of day * @param timeDefinition the definition of how to convert local to actual time, not null * @param savingAmountSecs the amount of saving from the standard offset after the transition in seconds * @return this, for chaining * @throws DateTimeException if a date-time field is out of range * @throws IllegalArgumentException if the day of month indicator is invalid * @throws IllegalArgumentException if the end of day midnight flag does not match the time * @throws IllegalStateException if no window has yet been added * @throws IllegalStateException if the window already has fixed savings * @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules */ public ZoneRulesBuilder addRuleToWindow( int startYear, int endYear, Month month, int dayOfMonthIndicator, DayOfWeek dayOfWeek, LocalTime time, boolean timeEndOfDay, TimeDefinition timeDefinition, int savingAmountSecs) { Jdk8Methods.requireNonNull(month, "month"); Jdk8Methods.requireNonNull(time, "time"); Jdk8Methods.requireNonNull(timeDefinition, "timeDefinition"); YEAR.checkValidValue(startYear); YEAR.checkValidValue(endYear); if (dayOfMonthIndicator < -28 || dayOfMonthIndicator > 31 || dayOfMonthIndicator == 0) { throw new IllegalArgumentException("Day of month indicator must be between -28 and 31 inclusive excluding zero"); } if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) { throw new IllegalArgumentException("Time must be midnight when end of day flag is true"); } if (windowList.isEmpty()) { throw new IllegalStateException("Must add a window before adding a rule"); } TZWindow window = windowList.get(windowList.size() - 1); window.addRule(startYear, endYear, month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition, savingAmountSecs); return this; }
@Test(dataProvider = "FloorMod") public void test_floorMod_int(long a, int b, int expected) { if (a <= Integer.MAX_VALUE && a >= Integer.MIN_VALUE) { assertEquals(Jdk8Methods.floorMod((int) a, b), expected); } }
@Override public ChronoPeriod plus(TemporalAmount amountToAdd) { if (amountToAdd instanceof ChronoPeriodImpl) { ChronoPeriodImpl amount = (ChronoPeriodImpl) amountToAdd; if (amount.getChronology().equals(getChronology())) { return new ChronoPeriodImpl( chronology, Jdk8Methods.safeAdd(years, amount.years), Jdk8Methods.safeAdd(months, amount.months), Jdk8Methods.safeAdd(days, amount.days)); } } throw new DateTimeException("Unable to add amount: " + amountToAdd); }
@Override HijrahDate plusYears(long years) { if (years == 0) { return this; } int newYear = Jdk8Methods.safeAdd(this.yearOfEra, (int)years); return HijrahDate.of(this.era, newYear, this.monthOfYear, this.dayOfMonth); }
/** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override public Year plus(long amountToAdd, TemporalUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { case YEARS: return plusYears(amountToAdd); case DECADES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 10)); case CENTURIES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 100)); case MILLENNIA: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 1000)); case ERAS: return with(ERA, Jdk8Methods.safeAdd(getLong(ERA), amountToAdd)); } throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); } return unit.addTo(this, amountToAdd); }
@Override public ChronoPeriod multipliedBy(int scalar) { return new ChronoPeriodImpl( chronology, Jdk8Methods.safeMultiply(years, scalar), Jdk8Methods.safeMultiply(months, scalar), Jdk8Methods.safeMultiply(days, scalar)); }
/** * Returns a copy of this duration with the specified duration added. * <p> * This instance is immutable and unaffected by this method call. * * @param secondsToAdd the seconds to add, positive or negative * @param nanosToAdd the nanos to add, positive or negative * @return a {@code Duration} based on this duration with the specified seconds added, not null * @throws ArithmeticException if numeric overflow occurs */ private Duration plus(long secondsToAdd, long nanosToAdd) { if ((secondsToAdd | nanosToAdd) == 0) { return this; } long epochSec = Jdk8Methods.safeAdd(seconds, secondsToAdd); epochSec = Jdk8Methods.safeAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); nanosToAdd = nanosToAdd % NANOS_PER_SECOND; long nanoAdjustment = nanos + nanosToAdd; // safe int+NANOS_PER_SECOND return ofSeconds(epochSec, nanoAdjustment); }
/** * Constructor. * * @param printerParser the printer/parser to use, not null * @param locale the locale to use, not null * @param decimalStyle the decimal style to use, not null * @param resolverStyle the resolver style to use, not null * @param resolverFields the fields to use during resolving, null for all fields * @param chrono the chronology to use, null for no override * @param zone the zone to use, null for no override */ DateTimeFormatter(CompositePrinterParser printerParser, Locale locale, DecimalStyle decimalStyle, ResolverStyle resolverStyle, Set<TemporalField> resolverFields, Chronology chrono, ZoneId zone) { this.printerParser = Jdk8Methods.requireNonNull(printerParser, "printerParser"); this.locale = Jdk8Methods.requireNonNull(locale, "locale"); this.decimalStyle = Jdk8Methods.requireNonNull(decimalStyle, "decimalStyle"); this.resolverStyle = Jdk8Methods.requireNonNull(resolverStyle, "resolverStyle"); this.resolverFields = resolverFields; this.chrono = chrono; this.zone = zone; }
@SuppressWarnings("unchecked") @Override public <R extends Temporal> R adjustInto(R dateTime, long newValue) { if (range().isValidValue(newValue) == false) { throw new DateTimeException("Invalid value: " + name + " " + newValue); } return (R) dateTime.with(EPOCH_DAY, Jdk8Methods.safeSubtract(newValue, offset)); }