
java.time.YearMonth.scala Maven / Gradle / Ivy
package java.time
import java.time.temporal._
/** Created by alonsodomin on 25/12/2015. */
final class YearMonth private (year: Int, month: Int)
extends TemporalAccessor with Temporal with TemporalAdjuster
with Comparable[YearMonth] with java.io.Serializable {
import Preconditions._
import ChronoField._
import ChronoUnit._
requireDateTime(year >= Year.MIN_VALUE && year <= Year.MAX_VALUE,
s"Invalid year: $year")
requireDateTime(month >= 1 && month <= 12, s"Invalid month: $month")
def isSupported(field: TemporalField): Boolean = field match {
case _: ChronoField =>
field == YEAR || field == YEAR_OF_ERA || field == MONTH_OF_YEAR ||
field == PROLEPTIC_MONTH || field == ERA
case null => false
case _ => field.isSupportedBy(this)
}
def isSupported(unit: TemporalUnit): Boolean = unit match {
case _: ChronoUnit =>
unit == MONTHS || unit == YEARS || unit == DECADES || unit == CENTURIES ||
unit == MILLENNIA || unit == ERAS
case null => false
case _ => unit.isSupportedBy(this)
}
// Implemented by TemporalAccessor
// def range(field: TemporalField): ValueRange
def getLong(field: TemporalField): Long = field match {
case YEAR => year
case YEAR_OF_ERA => if (year < 1) 1 - year else year
case MONTH_OF_YEAR => month
case PROLEPTIC_MONTH => prolepticMonth
case ERA => if (year < 1) 0 else 1
case _: ChronoField =>
throw new UnsupportedTemporalTypeException("Unsupported field: " + field)
case _ => field.getFrom(this)
}
private def prolepticMonth: Long = (year * 12.0 + (month - 1)).toLong
def getYear(): Int = year
def getMonthValue(): Int = month
def getMonth(): Month = Month.of(month)
def isLeapYear(): Boolean = Year.isLeap(year)
def isValidDay(dayOfMonth: Int): Boolean =
dayOfMonth >= 1 && dayOfMonth <= lengthOfMonth()
def lengthOfMonth(): Int = getMonth().length(isLeapYear())
def lengthOfYear(): Int = Year.of(year).length()
def `with`(field: TemporalField, value: Long): YearMonth = {
def withYearMonth(y: Int, m: Int): YearMonth = {
if (y == year && m == month) this
else YearMonth.of(y, m)
}
field match {
case YEAR =>
withYearMonth(YEAR.checkValidIntValue(value), month)
case YEAR_OF_ERA =>
val isoYear = YEAR.checkValidIntValue(
if (year < 1) 1 - value
else value
)
withYearMonth(isoYear, month)
case MONTH_OF_YEAR =>
withYearMonth(year, MONTH_OF_YEAR.checkValidIntValue(value))
case PROLEPTIC_MONTH =>
plusMonths(value - getLong(PROLEPTIC_MONTH))
case ERA =>
requireDateTime(value >= 0 && value <= 1, s"Invalid value for ERA: $value")
val era = getLong(ERA)
if (value == era) this
else withYearMonth(YEAR.checkValidIntValue(1 - year), month)
case _: ChronoField =>
throw new UnsupportedTemporalTypeException("Unsupported field: " + field)
case _ => field.adjustInto(this, value)
}
}
def withYear(year: Int): YearMonth = `with`(YEAR, year)
def withMonth(month: Int): YearMonth = `with`(MONTH_OF_YEAR, month)
def plus(amount: Long, unit: TemporalUnit): YearMonth = unit match {
case MONTHS => plusMonths(amount)
case YEARS => plusYears(amount)
case DECADES => plusYears(Math.multiplyExact(amount, 10))
case CENTURIES => plusYears(Math.multiplyExact(amount, 100))
case MILLENNIA => plusYears(Math.multiplyExact(amount, 1000))
case ERAS =>
val era = getLong(ERA)
`with`(ERA, Math.addExact(era, amount))
case _: ChronoUnit =>
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit)
case _ => unit.addTo(this, amount)
}
def plusYears(years: Long): YearMonth = {
if (years == 0) {
this
} else {
// Allowing the Long to overflow to align with JDK implementation
val newYear = year + years
new YearMonth(YEAR.checkValidIntValue(newYear), month)
}
}
def plusMonths(months: Long): YearMonth = {
if (months == 0) {
this
} else {
// Allowing the Long to overflow to align with JDK implementation
val newProlepticMonth = prolepticMonth + months
val newYear = Math.floorDiv(newProlepticMonth, 12)
val newMonth = Math.floorMod(newProlepticMonth, 12) + 1
new YearMonth(
YEAR.checkValidIntValue(newYear),
MONTH_OF_YEAR.checkValidIntValue(newMonth)
)
}
}
override def minus(amount: TemporalAmount): YearMonth =
super.minus(amount).asInstanceOf[YearMonth]
override def minus(amount: Long, unit: TemporalUnit): YearMonth =
super.minus(amount, unit).asInstanceOf[YearMonth]
def minusYears(years: Long): YearMonth = minus(years, YEARS)
def minusMonths(months: Long): YearMonth = minus(months, MONTHS)
// Not implemented
// def query[R](query: TemporalQuery[R]): R
def adjustInto(temporal: Temporal): Temporal =
temporal.`with`(PROLEPTIC_MONTH, prolepticMonth)
def until(endExclusive: Temporal, unit: TemporalUnit): Long = {
def other: YearMonth = YearMonth.from(endExclusive)
def monthsDiff: Long = other.prolepticMonth - prolepticMonth
unit match {
case MONTHS => monthsDiff
case YEARS => monthsDiff / 12
case DECADES => until(endExclusive, YEARS) / 10
case CENTURIES => until(endExclusive, YEARS) / 100
case MILLENNIA => until(endExclusive, YEARS) / 1000
case ERAS => other.getLong(ERA) - getLong(ERA)
case _: ChronoUnit =>
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit)
case _ => unit.between(this, endExclusive)
}
}
def atDay(dayOfMonth: Int): LocalDate =
LocalDate.of(year, month, dayOfMonth)
def atEndOfMonth: LocalDate =
atDay(getMonth().length(isLeapYear()))
def compareTo(other: YearMonth): Int =
if (year == other.getYear) month - other.getMonthValue
else year - other.getYear
def isAfter(other: YearMonth): Boolean = compareTo(other) > 0
def isBefore(other: YearMonth): Boolean = compareTo(other) < 0
override def equals(other: Any): Boolean = other match {
case that: YearMonth =>
year == that.getYear && month == that.getMonthValue
case _ => false
}
override def hashCode(): Int = year + (month << 27)
override def toString: String = f"$year%04d-$month%02d"
// Not implemented
// def format(formatter: DateTimeFormatter): String
}
object YearMonth {
import ChronoField._
def now(): YearMonth = from(LocalDate.now())
// Not implemented
// def now(zoneId: ZoneId): YearMonth
// def now(clock: Clock): YearMonth
def of(year: Int, month: Month): YearMonth = {
if (month == null) throw new NullPointerException("month")
of(year, month.getValue)
}
def of(year: Int, month: Int): YearMonth = {
YEAR.checkValidIntValue(year)
MONTH_OF_YEAR.checkValidIntValue(month)
new YearMonth(year, month)
}
def from(temporal: TemporalAccessor): YearMonth = temporal match {
case temporal: YearMonth => temporal
case _ => of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR))
}
// Not implemented
// def parse(text: CharSequence): YearMonth
// def parse(text: CharSequence, formatter: DateTimeFormatter): YearMonth
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy