Class PersianDate

java.lang.Object
com.github.mfathi91.time.PersianDate
All Implemented Interfaces:
java.lang.Comparable<java.time.chrono.ChronoLocalDate>, java.time.chrono.ChronoLocalDate, java.time.temporal.Temporal, java.time.temporal.TemporalAccessor, java.time.temporal.TemporalAdjuster

@Immutable
public final class PersianDate
extends java.lang.Object
implements java.time.chrono.ChronoLocalDate
This is an implementation of Solar Hijri calendar (also known as Jalali calendar, Persian calendar).

PersianDate is an immutable date-time object that represents a date, often viewed as year-month-day.

In order to simplify usage of this class, it is tried to make API of this class the same as JDK8 LocalDate class. Since some methods of LocalDate were useful for Persian calendar system, they have been exactly copied. Some other methods of HijrahDate and JapaneseDate have been modified and used in this class.

This class is immutable and can be used in multi-threaded programs.

Author:
Mahmoud Fathi
  • Field Summary

    Fields
    Modifier and Type Field Description
    static PersianDate MAX
    The maximum supported persian date 1999-12-29.
    static PersianDate MIN
    The minimum supported persian date 0001-01-01.
  • Method Summary

    Modifier and Type Method Description
    boolean equals​(java.lang.Object obj)
    Checks if this date is equal to another date.
    static PersianDate from​(java.time.temporal.TemporalAccessor temporal)
    Obtains an instance of PersianDate from a temporal object.
    static PersianDate fromGregorian​(java.time.LocalDate localDate)
    Returns an instance of PersianDate that is correspondent to the gregorian date of parameter localDate.
    java.time.chrono.Chronology getChronology()
    Gets the chronology of this date, which is the Persian calendar system.
    int getDayOfMonth()  
    java.time.DayOfWeek getDayOfWeek()
    Returns day-of-week as an enum DayOfWeek.
    int getDayOfYear()  
    long getLong​(java.time.temporal.TemporalField field)
    Gets the value of the specified field from this date as a long.
    PersianMonth getMonth()  
    int getMonthValue()  
    int getYear()  
    int hashCode()
    A hash code for this persian date.
    boolean isLeapYear()
    Returns true if year is a leap year in Persian calendar.
    static boolean isLeapYear​(int year)
    Returns true if the given year is a leap year in Persian calendar.
    int lengthOfMonth()
    Returns the length of the month represented by this date.
    static PersianDate now()
    Obtains current Persian date from the system clock in the default time zone.
    static PersianDate of​(int year, int month, int dayOfMonth)
    Obtains an instance of PersianDate with year, month and day of month.
    static PersianDate of​(int year, PersianMonth month, int dayOfMonth)
    Obtains an instance of PersianDate with year, month and day of month.
    static PersianDate ofEpochDay​(long epochDays)
    Returns an instance of PersianDate, based on number of epoch days, which is from 1970-01-01.
    static PersianDate ofJulianDays​(long julianDays)
    Returns an instance of PersianDate, based on number of julian days.
    static PersianDate parse​(java.lang.CharSequence text)
    Obtains an instance of PersianDate from a text, assuming its format is yyyy-MM-dd.
    static PersianDate parse​(java.lang.CharSequence text, java.time.format.DateTimeFormatter formatter)
    Obtains an instance of PersianDate from a text string using a specific formatter.
    PersianDate plusDays​(long daysToAdd)
    Returns a copy of this PersianDate with the specified number of days added.
    PersianDate plusMonths​(long monthsToAdd)
    Returns a copy of this PersianDate with the specified period in months added.
    PersianDate plusYears​(long yearsToAdd)
    Returns a copy of this PersianDate with the specified period in years added.
    long toEpochDay()  
    java.time.LocalDate toGregorian()
    Returns an equivalent Gregorian date and time as an instance of LocalDate.
    long toJulianDay()
    Returns number of corresponding julian days.
    java.lang.String toString()
    Returns the string representation of this persian date.
    java.time.chrono.ChronoPeriod until​(java.time.chrono.ChronoLocalDate endDateExclusive)
    Calculates the period between this date and another date as a Period.
    long until​(java.time.temporal.Temporal endExclusive, java.time.temporal.TemporalUnit unit)
    Calculates the amount of time until another date in terms of the specified unit.

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait

    Methods inherited from interface java.time.chrono.ChronoLocalDate

    adjustInto, atTime, compareTo, format, getEra, isAfter, isBefore, isEqual, isSupported, isSupported, lengthOfYear, minus, minus, plus, plus, query, with, with

    Methods inherited from interface java.time.temporal.TemporalAccessor

    get, range
  • Field Details

    • MIN

      public static final PersianDate MIN
      The minimum supported persian date 0001-01-01.
    • MAX

      public static final PersianDate MAX
      The maximum supported persian date 1999-12-29.
  • Method Details

    • getYear

      public int getYear()
      Returns:
      the year
    • getMonth

      public PersianMonth getMonth()
      Returns:
      the month-of-year field using the Month enum.
      See Also:
      getMonthValue()
    • getMonthValue

      public int getMonthValue()
      Returns:
      the month-of-year, from 1 to 12
      See Also:
      getMonth()
    • getDayOfMonth

      public int getDayOfMonth()
      Returns:
      day-of-month, from 1 to 31
    • getDayOfYear

      public int getDayOfYear()
      Returns:
      day-of-year, from 1 to 365 or 366 in a leap year
    • getDayOfWeek

      public java.time.DayOfWeek getDayOfWeek()
      Returns day-of-week as an enum DayOfWeek. This avoids confusion as to what int means. If you need access to the primitive int value then the enum provides the int value.
      Returns:
      day-of-week, which is an enum DayOfWeek
    • now

      public static PersianDate now()
      Obtains current Persian date from the system clock in the default time zone.
      Returns:
      current Persian date from the system clock in the default time zone
    • of

      public static PersianDate of​(int year, int month, int dayOfMonth)
      Obtains an instance of PersianDate with year, month and day of month. The value of month must be between 1 and 12. Value 1 would be PersianMonth.FARVARDIN and value 12 represents PersianMonth.ESFAND.
      Parameters:
      year - the year to represent, from 1 to MAX_YEAR
      month - the value of month, from 1 to 12
      dayOfMonth - the dayOfMonth to represent, from 1 to 31
      Returns:
      an instance of PersianDate
      Throws:
      java.time.DateTimeException - if the passed parameters do not form a valid date or time.
    • of

      public static PersianDate of​(int year, PersianMonth month, int dayOfMonth)
      Obtains an instance of PersianDate with year, month and day of month.
      Parameters:
      year - the year to represent, from 1 to MAX_YEAR
      month - the month-of-year to represent, an instance of PersianMonth
      dayOfMonth - the dayOfMonth to represent, from 1 to 31
      Returns:
      an instance of PersianDate
      Throws:
      java.time.DateTimeException - if the passed parameters do not form a valid date or time.
    • fromGregorian

      public static PersianDate fromGregorian​(java.time.LocalDate localDate)
      Returns an instance of PersianDate that is correspondent to the gregorian date of parameter localDate.
      Parameters:
      localDate - Gregorian date and time, not null
      Returns:
      an equivalent Persian date and time as an instance of PersianDate
    • parse

      public static PersianDate parse​(java.lang.CharSequence text)
      Obtains an instance of PersianDate from a text, assuming its format is yyyy-MM-dd. For example the given text could be 1399-10-12, otherwise an exception will be thrown.
      Parameters:
      text - the text to parse, not null
      Returns:
      an instance of PersianDate from the given text
    • parse

      public static PersianDate parse​(java.lang.CharSequence text, java.time.format.DateTimeFormatter formatter)
      Obtains an instance of PersianDate from a text string using a specific formatter.
      Parameters:
      text - the text to parse, not null
      formatter - the formatter to use, not null
      Returns:
      an instance of PersianDate from the given text
    • from

      public static PersianDate from​(java.time.temporal.TemporalAccessor temporal)
      Obtains an instance of PersianDate from a temporal object.
      Parameters:
      temporal - the temporal object to convert, not null
      Returns:
      the local date, not null
      Throws:
      java.time.DateTimeException - if unable to convert to a PersianDate
    • ofEpochDay

      public static PersianDate ofEpochDay​(long epochDays)
      Returns an instance of PersianDate, based on number of epoch days, which is from 1970-01-01. For example passing 17468 as the parameter results a persian date of 1396-08-07.
      Parameters:
      epochDays - epoch days
      Returns:
      an instance of PersianDate
    • ofJulianDays

      public static PersianDate ofJulianDays​(long julianDays)
      Returns an instance of PersianDate, based on number of julian days. For example passing 2458055 as the parameter will cause to get a Persian date of "1396-8-6".
      Parameters:
      julianDays - julian days
      Returns:
      an instance of PersianDate
      See Also:
      libcalendars
    • getChronology

      public java.time.chrono.Chronology getChronology()
      Gets the chronology of this date, which is the Persian calendar system.

      The Chronology represents the calendar system in use. The era and other fields in ChronoField are defined by the chronology.

      Specified by:
      getChronology in interface java.time.chrono.ChronoLocalDate
      Returns:
      the Persian chronology, not null
    • lengthOfMonth

      public int lengthOfMonth()
      Returns the length of the month represented by this date.

      This returns the length of the month in days.

      Specified by:
      lengthOfMonth in interface java.time.chrono.ChronoLocalDate
      Returns:
      the length of the month in days
    • until

      public long until​(java.time.temporal.Temporal endExclusive, java.time.temporal.TemporalUnit unit)
      Calculates the amount of time until another date in terms of the specified unit.

      This calculates the amount of time between two PersianDate objects in terms of a single TemporalUnit. The start and end points are this and the specified date. The result will be negative if the end is before the start. The Temporal passed to this method is converted to a PersianDate using from(TemporalAccessor). For example, the amount in days between two dates can be calculated using startDate.until(endDate, DAYS).

      The calculation returns a whole number, representing the number of complete units between the two dates. For example, the amount in months between 1396-06-15 and 1396-08-14 will only be one month as it is one day short of two months.

      There are two equivalent ways of using this method. The first is to invoke this method. The second is to use TemporalUnit.between(Temporal, Temporal):

         // these two lines are equivalent
         amount = start.until(end, MONTHS);
         amount = MONTHS.between(start, end);
       
      The choice should be made based on which makes the code more readable.

      The calculation is implemented in this method for ChronoUnit. The units DAYS, WEEKS, MONTHS, YEARS, DECADES, CENTURIES, MILLENNIA and ERAS are supported. Other ChronoUnit values will throw an exception.

      If the unit is not a ChronoUnit, then the result of this method is obtained by invoking TemporalUnit.between(Temporal, Temporal) passing this as the first argument and the converted input temporal as the second argument.

      This instance is immutable and unaffected by this method call.

      Specified by:
      until in interface java.time.chrono.ChronoLocalDate
      Specified by:
      until in interface java.time.temporal.Temporal
      Parameters:
      endExclusive - the end date, exclusive, which is converted to a PersianDate, not null
      unit - the unit to measure the amount in, not null
      Returns:
      the amount of time between this date and the end date
      Throws:
      java.time.DateTimeException - if the amount cannot be calculated, or the end temporal cannot be converted to a PersianDate
      java.time.temporal.UnsupportedTemporalTypeException - if the unit is not supported
      java.lang.ArithmeticException - if numeric overflow occurs
    • until

      public java.time.chrono.ChronoPeriod until​(java.time.chrono.ChronoLocalDate endDateExclusive)
      Calculates the period between this date and another date as a Period.

      This calculates the period between two dates in terms of years, months and days. The start and end points are this and the specified date. The result will be negative if the end is before the start. The negative sign will be the same in each of year, month and day.

      The calculation is performed using the ISO calendar system. If necessary, the input date will be converted to ISO.

      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 normalized into years and months based on a 12 month year. A month is considered to be complete if the end day-of-month is greater than or equal to the start day-of-month. For example, from 2010-01-15 to 2011-03-18 is "1 year, 2 months and 3 days".

      There are two equivalent ways of using this method. The first is to invoke this method. The second is to use Period.between(LocalDate, LocalDate):

         // these two lines are equivalent
         period = start.until(end);
         period = Period.between(start, end);
       
      The choice should be made based on which makes the code more readable.
      Specified by:
      until in interface java.time.chrono.ChronoLocalDate
      Parameters:
      endDateExclusive - the end date, exclusive, which may be in any chronology, not null
      Returns:
      the period between this date and the end date, not null
    • getLong

      public long getLong​(java.time.temporal.TemporalField field)
      Gets the value of the specified field from this date as a long.

      This queries this date for the value for the specified field. If it is not possible to return the value, because the field is not supported or for some other reason, an exception is thrown.

      If the field is a ChronoField then the query is implemented here. The supported fields will return valid values based on this date. All other ChronoField instances will throw an UnsupportedTemporalTypeException.

      If the field is not a ChronoField, then the result of this method is obtained by invoking TemporalField.getFrom(TemporalAccessor) passing this as the argument. Whether the value can be obtained, and what the value represents, is determined by the field.

      Specified by:
      getLong in interface java.time.temporal.TemporalAccessor
      Parameters:
      field - the field to get, not null
      Returns:
      the value for the field
      Throws:
      java.time.DateTimeException - if a value for the field cannot be obtained
      java.time.temporal.UnsupportedTemporalTypeException - if the field is not supported
      java.lang.ArithmeticException - if numeric overflow occurs
    • plusYears

      public PersianDate plusYears​(long yearsToAdd)
      Returns a copy of this PersianDate with the specified period in years added.

      This method adds the specified amount to the years field in three steps:

      1. Add the input years to the year field
      2. Check if the resulting date would be invalid
      3. Adjust the day-of-month to the last valid day if necessary

      For example, 1387-12-30 (leap year) plus one year would result in the invalid date 1388-12-30 (standard year). Instead of returning an invalid result, the last valid day of the month, 1388-12-29, is selected instead.

      This instance is immutable and unaffected by this method call.

      Parameters:
      yearsToAdd - the years to add, may be negative
      Returns:
      a PersianDate based on this date with the years added, not null
      Throws:
      java.time.DateTimeException - if the result exceeds the supported date range
    • plusMonths

      public PersianDate plusMonths​(long monthsToAdd)
      Returns a copy of this PersianDate with the specified period in months added.

      This method adds the specified amount to the months field in three steps:

      1. Add the input months to the month-of-year field
      2. Check if the resulting date would be invalid
      3. Adjust the day-of-month to the last valid day if necessary

      For example, 1388-11-30 plus one month would result in the invalid date 1388-12-30. Instead of returning an invalid result, the last valid day of the month, 1388-12-29, is selected instead.

      This instance is immutable and unaffected by this method call.

      Parameters:
      monthsToAdd - the months to add, may be negative
      Returns:
      a PersianDate based on this date with the months added, not null
      Throws:
      java.time.DateTimeException - if the result exceeds the supported date range
    • plusDays

      public PersianDate plusDays​(long daysToAdd)
      Returns a copy of this PersianDate with the specified number of days added.

      This method adds the specified amount to the days field incrementing the month and year fields as necessary to ensure the result remains valid. The result is only invalid if the maximum/minimum year is exceeded.

      For example, 1396-12-29 plus one day would result in 1397-01-01.

      This instance is immutable and unaffected by this method call.

      Parameters:
      daysToAdd - the days to add, may be negative
      Returns:
      a PersianDate based on this date with the days added, not null
      Throws:
      java.time.DateTimeException - if the result exceeds the supported date range
    • isLeapYear

      public boolean isLeapYear()
      Returns true if year is a leap year in Persian calendar.
      Specified by:
      isLeapYear in interface java.time.chrono.ChronoLocalDate
      Returns:
      true if year is a leap year in Persian calendar
    • isLeapYear

      public static boolean isLeapYear​(int year)
      Returns true if the given year is a leap year in Persian calendar.
      Parameters:
      year - the year to be checked
      Returns:
      true if the given year is a leap year in Persian calendar.
    • toGregorian

      public java.time.LocalDate toGregorian()
      Returns an equivalent Gregorian date and time as an instance of LocalDate. Calling this method has no effect on the object that calls this.
      Returns:
      the equivalent Gregorian date as an instance of LocalDate
    • toEpochDay

      public long toEpochDay()
      Specified by:
      toEpochDay in interface java.time.chrono.ChronoLocalDate
    • toJulianDay

      public long toJulianDay()
      Returns number of corresponding julian days. For number of juliand days of PersianDate.of(1396, 8, 6) is 2458054.

      Calling this method has no effect on this instance.

      Returns:
      number of corresponding julian days
      See Also:
      calendar convertor
    • equals

      public boolean equals​(java.lang.Object obj)
      Checks if this date is equal to another date.

      Compares this PersianDate with another ensuring that the date is the same.

      Specified by:
      equals in interface java.time.chrono.ChronoLocalDate
      Overrides:
      equals in class java.lang.Object
      Parameters:
      obj - the object to check, null returns false
      Returns:
      true if this is equal to the other date
    • hashCode

      public int hashCode()
      A hash code for this persian date.
      Specified by:
      hashCode in interface java.time.chrono.ChronoLocalDate
      Overrides:
      hashCode in class java.lang.Object
      Returns:
      a suitable hash code
    • toString

      public java.lang.String toString()
      Returns the string representation of this persian date. The string contains of ten characters whose format is "XXXX-YY-ZZ", where XXXX is the year, YY is the month-of-year and ZZ is day-of-month. (Each of the capital characters represents a single decimal digit.)

      If any of the three parts of this persian date is too small to fill up its field, the field is padded with leading zeros.

      Specified by:
      toString in interface java.time.chrono.ChronoLocalDate
      Overrides:
      toString in class java.lang.Object
      Returns:
      a suitable representation of this persian date