Package com.google.gdata.data

Source Code of com.google.gdata.data.DateTime

/* Copyright (c) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package com.google.gdata.data;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
* Represents a date/time, or a date without a time.  Optionally
* includes a time zone.
*/
public class DateTime implements Comparable<Object> {


  public DateTime() {}


  public DateTime(long value) {
    this.value = value;
  }


  public DateTime(Date value) {
    this.value = value.getTime();
  }


  public DateTime(long value, int tzShift) {
    this.value = value;
    this.tzShift = new Integer(tzShift);
  }


  public DateTime(Date value, TimeZone zone) {
    this.value = value.getTime();
    this.tzShift = zone.getOffset(value.getTime()) / 60000;
  }


  public static DateTime now() {
    return new DateTime(new Date(), GMT);
  }


  /**
   * Date/time value expressed as the number of ms since the Unix epoch.
   *
   * If the time zone is specified, this value is normalized to UTC, so
   * to format this date/time value, the time zone shift has to be applied.
   */
  protected long value = 0;
  public long getValue() { return value; }
  public void setValue(long v) { value = v; }


  /** Specifies whether this is a date-only value. */
  protected boolean dateOnly = false;
  public boolean isDateOnly() { return dateOnly; }
  public void setDateOnly(boolean v) { dateOnly = v; }


  /**
   * Time zone shift from UTC in minutes. If {@code null}, no time zone
   * is set, and the time is always interpreted as local time.
   */
  protected Integer tzShift = null;
  public Integer getTzShift() { return tzShift; }
  public void setTzShift(Integer v) { tzShift = v; }


  @Override
  public int hashCode() {
    return Long.valueOf(value).hashCode();
  }

  /**
   * Compares instance with DateTime or Date objects.
   *
   * Does not take the tzShift value into account.
   * Therefore, two DateTime objects are equal independent to
   * the time zone they refer to.
   * Equals with a instance of java.util.Date is asymmetric.
   */
  @Override
  public boolean equals(Object o) {

    if (o instanceof DateTime) {

      return this.value == ((DateTime) o).value;

    } else if (o instanceof Date) {

      return this.value == ((Date) o).getTime();

    } else {

      return false;
    }
  }


  public int compareTo(Object o) {

    if (o instanceof DateTime) {
      return new Long(value).compareTo(new Long(((DateTime) o).value));
    } else if (o instanceof Date) {
      return new Long(value).compareTo(new Long(((Date) o).getTime()));
    } else {
      throw new RuntimeException("Invalid type.");
    }
  }


  /** XML date/time pattern. */
  public static final Pattern dateTimePattern =
    Pattern.compile("(\\d\\d\\d\\d)\\-(\\d\\d)\\-(\\d\\d)[Tt]" +
                    "(\\d\\d):(\\d\\d):(\\d\\d)(\\.(\\d+))?" +
                    "([Zz]|((\\+|\\-)(\\d\\d):(\\d\\d)))?");


  /** XML date pattern. */
  public static final Pattern datePattern =
    Pattern.compile("(\\d\\d\\d\\d)\\-(\\d\\d)\\-(\\d\\d)" +
                    "([Zz]|((\\+|\\-)(\\d\\d):(\\d\\d)))?");


  /** XML date/time or date pattern. */
  public static final Pattern dateTimeChoicePattern =
    Pattern.compile("(\\d\\d\\d\\d)\\-(\\d\\d)\\-(\\d\\d)" +
                    "([Tt](\\d\\d):(\\d\\d):(\\d\\d)(\\.(\\d+))?)?" +
                    "([Zz]|((\\+|\\-)(\\d\\d):(\\d\\d)))?");


  /** RFC 822 date/time format. */
  private static final SimpleDateFormat dateTimeFormat822 =
    new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);

  private static final TimeZone GMT = TimeZone.getTimeZone("GMT");

  static {
    dateTimeFormat822.setTimeZone(GMT);
  }


  /** Formats the value as an xs:date or xs:dateTime string. */
  @Override
  public String toString() {

    StringBuilder sb = new StringBuilder();

    Calendar dateTime = new GregorianCalendar(GMT);
    long localTime = value;
    if (tzShift != null) {
     localTime += tzShift.longValue() * 60000;
    }

    dateTime.setTimeInMillis(localTime);

    try {

      appendInt(sb, dateTime.get(Calendar.YEAR), 4);
      sb.append('-');
      appendInt(sb, dateTime.get(Calendar.MONTH) + 1, 2);
      sb.append('-');
      appendInt(sb, dateTime.get(Calendar.DAY_OF_MONTH), 2);

      if (!dateOnly) {

        sb.append('T');
        appendInt(sb, dateTime.get(Calendar.HOUR_OF_DAY), 2);
        sb.append(':');
        appendInt(sb, dateTime.get(Calendar.MINUTE), 2);
        sb.append(':');
        appendInt(sb, dateTime.get(Calendar.SECOND), 2);

        if (dateTime.isSet(Calendar.MILLISECOND)) {
          sb.append('.');
          appendInt(sb, dateTime.get(Calendar.MILLISECOND), 3);
        }
      }

      if (tzShift != null) {
       
        if (tzShift.intValue() == 0) {
         
          sb.append('Z');
         
        } else {
         
          int absTzShift = tzShift.intValue();
          if (tzShift > 0) {
            sb.append('+');
          } else {
            sb.append('-');
            absTzShift = -absTzShift;
          }
         
          int tzHours = absTzShift / 60;
          int tzMinutes = absTzShift % 60;
          appendInt(sb, tzHours, 2);
          sb.append(':');
          appendInt(sb, tzMinutes, 2);
        }
      }
    } catch (ArrayIndexOutOfBoundsException e) {
      throw new RuntimeException(e);
    }

    return sb.toString();
  }


  /** Formats the value as an RFC 822 date/time. */
  public String toStringRfc822() {
    assert !dateOnly;
    synchronized (dateTimeFormat822) {
      return dateTimeFormat822.format(value);
    }
  }


  /** Formats the value as a human-readable string. */
  public String toUiString() {

    StringBuilder sb = new StringBuilder();

    Calendar dateTime = new GregorianCalendar(GMT);
    long localTime = value;
    if (tzShift != null) {
     localTime += tzShift.longValue() * 60000;
    }

    dateTime.setTimeInMillis(localTime);

    try {

      appendInt(sb, dateTime.get(Calendar.YEAR), 4);
      sb.append('-');
      appendInt(sb, dateTime.get(Calendar.MONTH) + 1, 2);
      sb.append('-');
      appendInt(sb, dateTime.get(Calendar.DAY_OF_MONTH), 2);

      if (!dateOnly) {

        sb.append(' ');
        appendInt(sb, dateTime.get(Calendar.HOUR_OF_DAY), 2);
        sb.append(':');
        appendInt(sb, dateTime.get(Calendar.MINUTE), 2);
      }

    } catch (ArrayIndexOutOfBoundsException e) {
      throw new RuntimeException(e);
    }

    return sb.toString();
  }


  /** Parses an xs:dateTime string. */
  public static DateTime parseDateTime(String str)
      throws NumberFormatException {

    Matcher m = str == null ? null : dateTimePattern.matcher(str);

    if (str == null || !m.matches()) {
      throw new NumberFormatException("Invalid date/time format.");
    }

    /* Debugging help:
    System.out.println("Year: " + m.group(1));
    System.out.println("Month: " + m.group(2));
    System.out.println("Day: " + m.group(3));
    System.out.println("Hour: " + m.group(4));
    System.out.println("Minute: " + m.group(5));
    System.out.println("Second: " + m.group(6));
    System.out.println("Second Fraction: " + m.group(8));
    System.out.println("TZ: " + m.group(9));
    System.out.println("TZ Shift: " + m.group(11));
    System.out.println("TZ Hour: " + m.group(12));
    System.out.println("TZ Minute: " + m.group(13));
    */

    DateTime ret = new DateTime();
    ret.dateOnly = false;

    if (m.group(9) == null) {
      // No time zone specified.
    } else if (m.group(9).equalsIgnoreCase("Z")) {
      ret.tzShift = new Integer(0);
    } else {
      ret.tzShift = new Integer((Integer.valueOf(m.group(12)) * 60 +
                                 Integer.valueOf(m.group(13))));
      if (m.group(11).equals("-")) {
        ret.tzShift = new Integer(-ret.tzShift.intValue());
      }
    }

    Calendar dateTime = new GregorianCalendar(GMT);

    dateTime.clear();
    dateTime.set(Integer.valueOf(m.group(1)),
                 Integer.valueOf(m.group(2)) - 1,
                 Integer.valueOf(m.group(3)),
                 Integer.valueOf(m.group(4)),
                 Integer.valueOf(m.group(5)),
                 Integer.valueOf(m.group(6)));
    if (m.group(8) != null && m.group(8).length() > 0) {
      final BigDecimal bd = new BigDecimal("0." + m.group(8));
      // we care only for milliseconds, so movePointRight(3)
      dateTime.set(Calendar.MILLISECOND, bd.movePointRight(3).intValue());
    }

    ret.value = dateTime.getTimeInMillis();
    if (ret.tzShift != null) {
      ret.value -= ret.tzShift.intValue() * 60000;
    }

    return ret;
  }

  /** Parses an xs:date string. */
  public static DateTime parseDate(String str)
      throws NumberFormatException {

    Matcher m = str == null ? null : datePattern.matcher(str);

    if (str == null || !m.matches()) {
      throw new NumberFormatException("Invalid date format.");
    }

    /* Debugging help:
    System.out.println("Year: " + m.group(1));
    System.out.println("Month: " + m.group(2));
    System.out.println("Day: " + m.group(3));
    System.out.println("TZ: " + m.group(4));
    System.out.println("TZ Shift: " + m.group(6));
    System.out.println("TZ Hour: " + m.group(7));
    System.out.println("TZ Minute: " + m.group(8));
    */

    DateTime ret = new DateTime();
    ret.dateOnly = true;

    if (m.group(4) == null) {
      // No time zone specified.
    } else if (m.group(4).equalsIgnoreCase("Z")) {
      ret.tzShift = new Integer(0);
    } else {
      ret.tzShift = new Integer((Integer.valueOf(m.group(7)) * 60 +
                                 Integer.valueOf(m.group(8))));
      if (m.group(6).equals("-")) {
        ret.tzShift = new Integer(-ret.tzShift.intValue());
      }
    }

    Calendar dateTime = new GregorianCalendar(GMT);

    dateTime.clear();
    dateTime.set(Integer.valueOf(m.group(1)),
                 Integer.valueOf(m.group(2)) - 1,
                 Integer.valueOf(m.group(3)));

    ret.value = dateTime.getTimeInMillis();
    if (ret.tzShift != null) {
      ret.value -= ret.tzShift.intValue() * 60000;
    }

    return ret;
  }

  /**
   * Parses an XML value that's either an xs:date or xs:dateTime string.
   *
   * @throws  NumberFormatException
   *            Invalid RFC 3339 date or date/time string.
   */
  public static DateTime parseDateTimeChoice(String value)
      throws NumberFormatException {

    NumberFormatException exception;

    try {
      return DateTime.parseDateTime(value);
    } catch (NumberFormatException e) {
      exception = e;
    }

    try {
      return DateTime.parseDate(value);
    } catch (NumberFormatException e) {
      exception = e;
    }

    throw exception;
  }


  /** Appends a zero-padded number to a string builder. */
  private static void appendInt(StringBuilder sb, int num, int numDigits) {

    if (num < 0) {
      sb.append('-');
      num = -num;
    }

    char[] digits = new char[numDigits];
    for (int digit = numDigits - 1; digit >= 0; --digit) {
      digits[digit] = (char)('0' + num % 10);
      num /= 10;
    }

    sb.append(digits);
  }
}
TOP

Related Classes of com.google.gdata.data.DateTime

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.