
package w3c.pics.parser;

import java.util.*;

/**
 * A Class for constructing dates conforming to the ISO 8601 standard.
 **/

public class IsoDate {

  Calendar thecal = null;
  boolean add_one = false;

  /**
   * Creates a new IsoDate for the current time.
   **/

  public IsoDate() {
    String[] ids = TimeZone.getAvailableIDs(-5 * 60 * 60 * 1000);
    // if no ids were returned, something is wrong. get out.
    if (ids.length == 0)
      System.exit(0);
    // begin output
    SimpleTimeZone edt = new SimpleTimeZone(-5 * 60 * 60 * 1000, ids[0]);
    // set up rules for daylight savings time
    edt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
    edt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
    thecal = new GregorianCalendar(edt);
    Date trialTime = new Date();
    thecal.setTime(trialTime);
    if (edt.inDaylightTime(trialTime))
      add_one = true;
  }

  /**
   * Get the year as four digits
   * @return An int containing the year.
   **/

  private int getYear() {
    int dyear = thecal.get(Calendar.YEAR);
    return dyear;
  }

  /**
   * Get the month as two digits (01-12)
   * @return A String containing the month number.
   **/

  private String getMonthString() {
    int dmonth = thecal.get(Calendar.MONTH);
    switch (dmonth) {
    case 0:
      return "01";
    case 1:
      return "02";
    case 2:
      return "03";
    case 3:
      return "04";
    case 4:
      return "05";
    case 5:
      return "06";
    case 6:
      return "07";
    case 7:
      return "08";
    case 8:
      return "09";
    case 9:
      return "10";
    case 10:
      return "11";
    case 11:
      return "12";
    }
    return null;
  }

  /**
   * Get the date as two digits (01-31)
   * @return A String containing the date.
   **/

  private String getDateString() {
    int dday = thecal.get(Calendar.DATE);
    switch (dday) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      return new String("0"+dday);
    default:
      return Integer.toString(dday);
    }
  }

  /**
   * Get the minutes as two digits (00-59)
   * @return A String containing the minutes.
   **/

  private String getMinutesString() {
    int dmin = thecal.get(Calendar.MINUTE);
    switch (dmin) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      return new String("0"+dmin);
    default:
      return Integer.toString(dmin);
    }
  }

  /**
   * Get the hours as two digits (00-23)
   * @return A String containing the hours.
   **/

  private String getHoursString() {
    // int dhour = super.getHours();
    int dhour = thecal.get(Calendar.HOUR_OF_DAY);
    switch (dhour) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      return new String("0"+dhour);
    default:
      return Integer.toString(dhour);
    }
  }

  /**
   * Get the timezone offset.  It has the format [+/-]xxxx.
   * @return A String containing the timezone offset.
   **/

  private String getTZString() {
    // int offset = super.getTimezoneOffset();
    /* TimeZone tz = thecal.getTimeZone();
       int offset = tz.getRawOffset();*/
    String hoursstring = null;
    String minstring = null;
    int offset = (thecal.get(Calendar.ZONE_OFFSET))/(60*1000);
    int hours = offset/60;
    if (add_one)
      hours = hours + 1;
    int mins = offset%60;
    switch (hours) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      hoursstring = "0"+hours;
      break;
    default:
      hoursstring = Integer.toString(hours);
    }
    switch (mins) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      minstring = "0"+mins;
      break;
    default:
      minstring = Integer.toString(mins);
    }
    Integer realoffset = new Integer(hoursstring+minstring);
    offset = realoffset.intValue();
    if ((offset>=0)	&& (offset<=9))
      return new String("+000"+offset);
    else if ((offset>=10) && (offset<=99))
      return new String("+00"+offset);
    else if ((offset>=100) && (offset<=999))
      return new String("+0"+offset);
    else if (offset>=1000)
      return new String("+"+offset);
    else if ((offset<=0) && (offset>=-9)) 
      return new String("-000"+Integer.toString(-offset));
    else if ((offset<=-10) && (offset>=-99))
      return new String("-00"+Integer.toString(-offset));
    else if ((offset<=-100) && (offset>=-999))
      return new String("-0"+Integer.toString(-offset));
    else
      return new String(Integer.toString(offset));
  }

  /** 
   * Return the IsoDate as a String.
   * @return A String with the IsoDate.
   **/

  public String toString() {
    return new String("\""+getYear()+"."+getMonthString()+"."+getDateString()+
		      "T"+getHoursString()+":"+getMinutesString()+
		      getTZString()+"\"");
  }

  /**
   * Return the IsoDate as a String, using "-" instead of "." (Suitable for 
   * A PICSRules rule.)
   * @return A String with the IsoDate.
   **/

  public String toRuleString() {
    return new String("\""+getYear()+"-"+getMonthString()+"-"+getDateString()+
		      "T"+getHoursString()+":"+getMinutesString()+
		      getTZString()+"\"");
  }

  public static void main(String args[]) {
    IsoDate ID = new IsoDate();
    System.out.println("IsoDate: "+ID.toString());
  }
}
