You are here

class DatexJalali in Datex 7.2

Jalali calendar for datex.

Original conversion alogirthm by: Amin Saeedi. Forked from project: Shamsi-Date v4.0 (GPL). On github: github.com/amsa mail: amin.w3dev@gmail.com

Hierarchy

Expanded class hierarchy of DatexJalali

File

datex_api/DatexJalali.inc, line 87
Jalali calendar for datex.

View source
class DatexJalali extends DatexObject implements DatexCalendarIterface {

  // _________________________________ DATEX Variables.

  /**
   * number of days in a each Jalali month.
   */
  protected static $monthDays = array(
    31,
    31,
    31,
    31,
    31,
    31,
    30,
    30,
    30,
    30,
    30,
    29,
  );

  /**
   * Persian equivalanat of english numbers.
   */
  protected static $numbers = array(
    '۰',
    '۱',
    '۲',
    '۳',
    '۴',
    '۵',
    '۶',
    '۷',
    '۸',
    '۹',
  );

  /*
   * Translated names of days, month, ...
   */
  protected static $names = array(
    'months' => array(
      0 => 'Farvardin',
      1 => 'Ordibehesht',
      2 => 'Khordad',
      3 => 'Tir',
      4 => 'Mordad',
      5 => 'Shahrivar',
      6 => 'Mehr',
      7 => 'Aban',
      8 => 'Azar',
      9 => 'Dei',
      10 => 'Bahman',
      11 => 'Esfand',
    ),
    'ampm' => array(
      'am' => 'Ghablazohr',
      'pm' => 'Badazohr',
    ),
    'day_abbr' => array(
      'sh',
      'y',
      'd',
      's',
      'ch',
      'p',
      'j',
    ),
    'day_abbr_short' => array(
      'sh',
      'y',
      'd',
      's',
      'ch',
      'p',
      'j',
    ),
    'day' => array(
      'Shanbe',
      'Yekshanbe',
      'Doshanbe',
      'Seshanbe',
      'Cheharshanbe',
      'Panjshanbe',
      'Jome',
    ),
    'order' => array(
      'Yekom',
      'Dovom',
      'Sevom',
      'Cheharom',
      'Panjom',
      'Sheshom',
      'Haftom',
      'Hashtom',
      'Nohom',
      'Dahom',
      'Yazdahom',
      'Davazdahom',
      'Sizdahom',
      'Chehardahom',
      'Panzdahom',
      'Shanzdahom',
      'Hefdahom',
      'Hejdahom',
      'Noozdahom',
      'Bistom',
      'Bisto yekom',
      'Bisto dovom',
      'Bisto sevom',
      'Bisto cheharom',
      'Bisto panjom',
      'Bisto sheshom',
      'Bisto haftom',
      'Bisto hashtom',
      'Bisto nohom',
      'Siom',
      'Sio yekom',
      'Sio dovom',
    ),
  );

  // __________________________________ Jalali calculation variables.

  /**
   * Constant used in calculating year.
   *
   * Length of a year Calculated by Khayam is 365.2422 days (approx.); but as
   * the years are getting shorter the new value (valid from year 1380
   * Per./2000 A.D.) is used instead.
   */
  protected static $khayamYear = 365.24218956;

  /**
   * Correction to khayami constant.
   *
   * Recent calculations has introduced a correcting factor, which Khayam could
   * not reach. This is used to better adjust length of each year in seconds.
   */
  protected static $khayamYearCorrection = 6.152E-8;

  /**
   * Reference table made by Khayam for leap years.
   */
  protected static $khayamii = array(
    5,
    9,
    13,
    17,
    21,
    25,
    29,
    34,
    38,
    42,
    46,
    50,
    54,
    58,
    62,
    67,
    71,
    75,
    79,
    83,
    87,
    91,
    95,
    100,
    104,
    108,
    112,
    116,
    120,
    124,
    0,
  );

  /**
   * Count of days at the end of each Persian month.
   */
  protected static $mCounter = array(
    0,
    31,
    62,
    93,
    124,
    155,
    186,
    216,
    246,
    276,
    306,
    336,
  );

  // _______________________________________________________ METHODS.

  /**
   * Function to return various info, Used by parent class.
   */
  public function getInfo($info) {
    switch ($info) {
      case 'numbers':
        return self::$numbers;
      case 'names':
        return self::$names;
      case 'month_days':
        return self::$monthDays;
      default:
        throw new Exception('Unknown info.');
    }
  }

  /**
   * Calculate format values which parent won't handle.
   */
  public function calendarFormat() {
    $day_of_week = self::dayOfWeek($this->year, $this->dayOfYear);
    return array(
      'w' => $day_of_week,
      'N' => $day_of_week + 1,
    );
  }

  /**
   * A parser for Jalali date strings.
   *
   *@TODO implement.
   */
  public static function parser($date, $format) {
    if (!(is_string($date) && is_string($format))) {
      throw new Exception('Datex parser: date or format not valid.');
    }
    $granularities = array();
    $j = $i = 0;
    $format_len = strlen($format);
    do {
      while (!ctype_alpha($format[$i]) && $i < $format_len) {
        $i++;
      }
      while (!ctype_digit($date[$j])) {
        $j++;
      }
      switch ($format[$i]) {
        case 'd':
          $granularities['day'] = $date[$j] . $date[++$j];
          break;
        case 'j':
          if (ctype_digit($date[$j + 1])) {
            $granularities['day'] = $date[$j] . $date[++$j];
          }
          else {
            $granularities['day'] = $date[$j];
          }
          break;
        case 'm':
          $granularities['month'] = $date[$j] . $date[++$j];
          break;
        case 'n':
          if (ctype_digit($date[$j + 1])) {
            $granularities['month'] = $date[$j] . $date[++$j];
          }
          else {
            $granularities['month'] = $date[$j];
          }
          break;
        case 'y':
        case 'Y':
          $granularities['year'] = $date[$j] . $date[++$j] . $date[++$j] . $date[++$j];
        case 'h':
          $granularities['hour'] = $date[$j] . $date[++$j];
          break;
        case 'g':
          if (ctype_digit($date[$j + 1])) {
            $granularities['hour'] = $date[$j] . $date[++$j];
          }
          else {
            $granularities['hour'] = $date[$j];
          }
          break;
        case 'H':
          $granularities['hour'] = $date[$j] . $date[++$j];
          break;
        case 'G':
          if (ctype_digit($date[$j + 1])) {
            $granularities['hour'] = $date[$j] . $date[++$j];
          }
          else {
            $granularities['hour'] = $date[$j];
          }
          break;
        case 'i':
          $granularities['minute'] = $date[$j] . $date[++$j];
          break;
        case 's':
          $granularities['second'] = $date[$j] . $date[++$j];
          break;
      }
      $j++;
    } while (++$i < $format_len);
    return $granularities;
  }

  /**
   * Converts a Gregorian date to Jalali.
   */
  public static function convert($timestamp, $offset = 0) {
    $timestamp = $timestamp + $offset;

    // DateTime will handle time.
    $ts = floor($timestamp % 60);
    $tm = floor($timestamp % 3600 / 60);
    $th = floor($timestamp % 86400 / 3600);
    $d = floor($timestamp / 86400) + 287;
    $y = floor($d / self::$khayamYear - $d * self::$khayamYearCorrection);
    $day_of_year = $d - round($y * self::$khayamYear, 0);
    if ($day_of_year == 0) {
      $day_of_year = 366;
    }
    $y += 1348;
    $m = 0;
    while ($m < 12 && $day_of_year > self::$mCounter[$m]) {
      $m++;
    }
    $d = $day_of_year - self::$mCounter[$m - 1];
    $day_of_week = self::dayOfWeek($y, $day_of_year);
    return array(
      $y,
      $m,
      $d,
      $th,
      $tm,
      $ts,
      $day_of_year,
      $day_of_week,
    );
  }

  /**
   * Converts a Jalali date to Gregorian.
   *
   * @TODO replcae with khayam calcualtion method.
   */
  public static function toGregorian($jalali_year = 0, $jalali_month = 0, $jalali_day = 0) {
    $now = self::convert(time());
    $jalali_year = ($jalali_year ? $jalali_year : $now[0]) - 979;
    $jalali_month = ($jalali_month ? $jalali_month : $now[1]) - 1;
    $jalali_day = ($jalali_day ? $jalali_day : $now[2]) - 1;
    $jalali_day_no = 365 * $jalali_year + intval($jalali_year / 33) * 8 + intval(($jalali_year % 33 + 3) / 4);
    for ($i = 0; $i < $jalali_month; ++$i) {
      $jalali_day_no += self::$monthDays[$i];
    }
    $jalali_day_no += $jalali_day;
    $gregorian_day_no = $jalali_day_no + 79;
    $g_year = 1600 + 400 * intval($gregorian_day_no / 146097);
    $gregorian_day_no = $gregorian_day_no % 146097;
    $leap = TRUE;
    if ($gregorian_day_no >= 36525) {
      $gregorian_day_no--;
      $g_year += 100 * intval($gregorian_day_no / 36524);
      $gregorian_day_no = $gregorian_day_no % 36524;
      if ($gregorian_day_no >= 365) {
        $gregorian_day_no++;
      }
      else {
        $leap = FALSE;
      }
    }
    $g_year += 4 * intval($gregorian_day_no / 1461);
    $gregorian_day_no %= 1461;
    if ($gregorian_day_no >= 366) {
      $leap = FALSE;
      $gregorian_day_no--;
      $g_year += intval($gregorian_day_no / 365);
      $gregorian_day_no = $gregorian_day_no % 365;
    }
    for ($i = 0; $gregorian_day_no >= self::$daysInGregorianMonth[$i] + ($i == 1 && $leap); $i++) {
      $gregorian_day_no -= self::$daysInGregorianMonth[$i] + ($i == 1 && $leap);
    }
    $g_month = $i + 1;
    $g_day = $gregorian_day_no + 1;
    return array(
      $g_year,
      $g_month,
      $g_day,
    );
  }

  /**
   * Returns non zero if given year is a leap year.
   */
  public static function isLeap($year) {
    $rasad = self::observationYear($year);
    $year = $rasad % 2820 % 128;
    $is_leap = array_search($year, self::$khayamii);
    return $is_leap;
  }

  /**
   * returns weekday of the specified day of the year. 1 to 7.
   */
  public static function dayOfWeek($year, $dayOfYear = 0) {
    $rasad = self::observationYear($year);
    $count2820 = floor($rasad / 2820);
    $mod2820 = $rasad % 2820;
    $count128 = floor($mod2820 / 128);
    $mod128 = $mod2820 % 128;
    $leapCount = 0;
    while ($mod128 > self::$khayamii[$leapCount]) {
      $leapCount++;
    }
    $yearStartDay = ($count2820 + 1) * 3 + $count128 * 5 + $mod128 + $leapCount;
    if ($dayOfYear > 0) {
      $dayOfYear--;
    }
    return ($yearStartDay + $dayOfYear) % 7;
  }

  /**
   * calculates the years from reference Observation year.
   */
  public static function observationYear($year) {
    return $year + 2346;
  }

  /**
   * Provides default arguments for INTL Formatter for this locale.
   */
  public function getIntlArgs() {
    static $default_intl_args = array(
      'fa_IR@calendar=persian',
      IntlDateFormatter::FULL,
      IntlDateFormatter::FULL,
      IntlDateFormatter::TRADITIONAL,
    );
    return $default_intl_args;
  }

  /**
   * Make up for missing granularities.
   *
   * Neccessary to get proper result while converting a date with a missing
   * granularity, Look at DatexCalendarInterface::fixGranularities for more
   * info.
   */
  public function fixMissingGranularities(array $granuls) {
    $offset = 0;
    if (!($granuls['hour'] || $granuls['minute'] || $granuls['second'])) {

      // 12 hours.
      $offset = 43200;
    }
    else {
      $offset = 0;
    }
    if (!($granuls['month'] || $granuls['day'])) {

      // 6 months.
      $offset += 16070400;
    }
    elseif (!$granuls['day']) {

      // 31 days.
      $offset += 2678400;
    }
    return $offset;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DatexJalali::$khayamii protected static property Reference table made by Khayam for leap years.
DatexJalali::$khayamYear protected static property Constant used in calculating year.
DatexJalali::$khayamYearCorrection protected static property Correction to khayami constant.
DatexJalali::$mCounter protected static property Count of days at the end of each Persian month.
DatexJalali::$monthDays protected static property number of days in a each Jalali month.
DatexJalali::$names protected static property
DatexJalali::$numbers protected static property Persian equivalanat of english numbers.
DatexJalali::calendarFormat public function Calculate format values which parent won't handle. Overrides DatexCalendarIterface::calendarFormat
DatexJalali::convert public static function Converts a Gregorian date to Jalali. Overrides DatexCalendarIterface::convert
DatexJalali::dayOfWeek public static function returns weekday of the specified day of the year. 1 to 7. Overrides DatexCalendarIterface::dayOfWeek
DatexJalali::fixMissingGranularities public function Make up for missing granularities. Overrides DatexCalendarIterface::fixMissingGranularities
DatexJalali::getInfo public function Function to return various info, Used by parent class. Overrides DatexCalendarIterface::getInfo
DatexJalali::getIntlArgs public function Provides default arguments for INTL Formatter for this locale. Overrides DatexCalendarIterface::getIntlArgs
DatexJalali::isLeap public static function Returns non zero if given year is a leap year. Overrides DatexCalendarIterface::isLeap
DatexJalali::observationYear public static function calculates the years from reference Observation year.
DatexJalali::parser public static function A parser for Jalali date strings.
DatexJalali::toGregorian public static function Converts a Jalali date to Gregorian. Overrides DatexCalendarIterface::toGregorian
DatexObject::$calendarFormats protected property Result of formats handled by extended class.
DatexObject::$day protected property Localized day value.
DatexObject::$daysInGregorianMonth protected static property Number of days in each Gregorian month. Leap year is not counted.
DatexObject::$formatString protected property Default format string.
DatexObject::$intlFormatter protected property IntlDateFormatter instance used by object instance.
DatexObject::$month protected property Localized month value.
DatexObject::$useINTL protected property Whether to use PHP-Intl or not.
DatexObject::$year protected property Localized year value.
DatexObject::checkSetTimezone protected function Check to see if given timezone is not NULL, Then if it's so, set it.
DatexObject::createINTLFormatter protected function Create an IntlDateFormatter fot this object.
DatexObject::decor public function Transliterate English numbers to localized numbers and vice versa.
DatexObject::difference public function Returns amount of time difference to another date object
DatexObject::fixByGranularities public function Helper method to make up for time difference if some granularites are missing.
DatexObject::format public function Similar to DateTime::format().
DatexObject::formatINTL protected function Format datetime using PHP-Intl.
DatexObject::formatPHP protected function Use php to format date
DatexObject::getFormat public function Returns format string set by setFormat.
DatexObject::getTzObject public static function Makes sure a tz is object, Not string ID of it.
DatexObject::getTzString public static function Makes sure $tz is string, Not tz object.
DatexObject::granularityNames public static function Names of date granularities.
DatexObject::hasINTL public static function Determines wether PECL package PHP-Intl is available or not.
DatexObject::monthFirstDay public function Returns an object containing first day of month.
DatexObject::monthLastDay public function Returns an object containing last day of month.
DatexObject::objectFromDate public function Created datex object from a localized date.
DatexObject::phpToIntl public static function Converts date format string (like 'Y-m-d') to it's PHP-Intl equivilant.
DatexObject::reset public function When new date or time is set on object, This method must be called.
DatexObject::setCalendarFormats protected function Call calendarFormat() on extended classes but hide storage details.
DatexObject::setConvert protected function Call extended class convert and set converted date on object instance,
DatexObject::setDate public function Same as DateTime::setDate().
DatexObject::setDatetime public function Set date-time of object instance by extracting timestamp from given date.
DatexObject::setDayBad public function A bad method which set's day directly.
DatexObject::setFormat public function Set default format string of object.
DatexObject::setIntlArgs public function Generate arguments passed to INTL formatter.
DatexObject::setIsLeap protected function Call extended class isLeap and set isLeap on object instance,
DatexObject::setTimestamp public function Same as DateTime::setTimestamp but also resets the object.
DatexObject::setTimezone public function Sets Time Zone of internal date object.
DatexObject::setUseINTL public function Set whether to use PHP-Intl or not.
DatexObject::toArray public function Returns this date object granularities, put in an array.
DatexObject::xformat public function Same as DateTime::format().
DatexObject::xobjectFromDate public function Creates a DateTime object containing date extracted from $date.
DatexObject::xsetDate public function Same as DateTime::setDate().
DatexObject::xsetDatetime public function Set date-time of object instance by extracting timestamp from given date.
DatexObject::xtoArray public function Same as DatexObject toArray but in Gregorian format.
DatexObject::__construct public function Constructor for DatexObject.
DatexObject::__toString public function Magic Function toString.