<?php
/**
 * Handle standard OSInet date code strings, uppercase
 * format: [y]ymdd
 * 4-characters until 2009-12-31, 5 afterwards
 *
 * $Id: u_date_code.php,v 1.3 2007-04-29 15:40:29 marand Exp $
 */

require_once('misc.php');          // needed for "iComparable" interface
require_once('boxed_scalars.php'); // needed to sign-compare ints

class osinet_date_code implements iComparable
  {
  private $f_value;

  /**
   * Implements iComparable restrictively, only comparing to other osinet_date_code
   * objects, not to any other class implementing iComparable
   *
   */
  public function cmp(iComparable $other)
    {
    if (!($other instanceof osinet_date_code))
      throw new Exception('osinet_date_code only compares to other osinet_date_code objects');

    $ar_d1 = $this->to_mkdate();
    $d1 = new boxed_int($ar_d1['mday']);
    $m1 = new boxed_int($ar_d1['mon']) ;
    $y1 = new boxed_int($ar_d1['year']);

    $ar_d2 = $other->to_mkdate();
    $d2 = new boxed_int($ar_d2['mday']);
    $m2 = new boxed_int($ar_d2['mon']) ;
    $y2 = new boxed_int($ar_d2['year']);

    $ret = $y1->cmp($y2);
    if ($ret)
      return $ret;
    else // same year
      {
      $ret = $m1->cmp($m2);
      if ($ret)
        return $ret;
      else // same year and month
        {
        $ret = $d1->cmp($d2);
        return $ret;
        }
      }
    }

  /**
   * Generate an mkdate()-like array for a date code
   *
   * @param string $date_code
   * @return array ['mday', 'mon', 'year']
   */
  public function to_mkdate()
    {
    $date_code = strtoupper($this->f_value);
    $matches = array();
    preg_match('/^([0-9]*)([A-Z])([0-9]?.*$)/', $date_code, $matches);
    if (count($matches) <> 4)
      {
      throw new Exception("Incorrect date code $date_code");
      }
    $ret = array(
      'mday' => $matches[3],
      'mon'  => ord($matches[2]) - ord('@'),
      'year' => 2000 + $matches[1],
      );
    return $ret;
    }

  public function __construct($time = null)
    {
    date_default_timezone_set('Europe/Paris');
    if (!$time)
      $time = time();
    $date = getdate();
    $day   = $date['mday'];
    $month = $date['mon'];
    $year  = $date['year'] % 100;

    $month = chr(ord('@') + $month);

    $this->f_value = sprintf('%d%s%02d', $year, $month, $day);
    }

  private function set_value($date_code)
    {
    $date_code = strtoupper($date_code);
    $matches = array();
    preg_match('/^([0-9]*)([A-Z])([0-9]?.*$)/', $date_code, $matches);
    if (count($matches) <> 4)
      {
      throw new Exception("Incorrect date code $date_code");
      }
    else
      $this->f_value = $date_code;
    }

  protected function __get($nm)
    {
    // echo "osinet_date_code::__get($nm)\n";
    if ($nm <> 'value')
      throw new Exception("$nm: undefined property for " . get_class($this));

    return $this->f_value;
    }

  private function __set($nm, $val)
    {
    if ($nm <> 'value')
      throw new Exception("$nm: undefined property for " . get_class($this));

    $this->set_value($val);
    }
  }