Home | History | Annotate | Download | only in impl
      1 // =================================================================================================
      2 // ADOBE SYSTEMS INCORPORATED
      3 // Copyright 2006 Adobe Systems Incorporated
      4 // All Rights Reserved
      5 //
      6 // NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
      7 // of the Adobe license agreement accompanying it.
      8 // =================================================================================================
      9 
     10 package com.adobe.xmp.impl;
     11 
     12 import java.util.Calendar;
     13 import java.util.Date;
     14 import java.util.GregorianCalendar;
     15 import java.util.Locale;
     16 import java.util.TimeZone;
     17 
     18 import com.adobe.xmp.XMPDateTime;
     19 import com.adobe.xmp.XMPException;
     20 
     21 
     22 /**
     23  * The implementation of <code>XMPDateTime</code>. Internally a <code>calendar</code> is used
     24  * plus an additional nano seconds field, because <code>Calendar</code> supports only milli
     25  * seconds. The <code>nanoSeconds</code> convers only the resolution beyond a milli second.
     26  *
     27  * @since 16.02.2006
     28  */
     29 public class XMPDateTimeImpl implements XMPDateTime
     30 {
     31 	/** */
     32 	private int year = 0;
     33 	/** */
     34 	private int month = 0;
     35 	/** */
     36 	private int day = 0;
     37 	/** */
     38 	private int hour = 0;
     39 	/** */
     40 	private int minute = 0;
     41 	/** */
     42 	private int second = 0;
     43 	/** Use the unversal time as default */
     44 	private TimeZone timeZone = TimeZone.getTimeZone("UTC");
     45 	/**
     46 	 * The nano seconds take micro and nano seconds, while the milli seconds are in the calendar.
     47 	 */
     48 	private int nanoSeconds;
     49 
     50 
     51 	/**
     52 	 * Creates an <code>XMPDateTime</code>-instance with the current time in the default time
     53 	 * zone.
     54 	 */
     55 	public XMPDateTimeImpl()
     56 	{
     57 		// EMPTY
     58 	}
     59 
     60 
     61 	/**
     62 	 * Creates an <code>XMPDateTime</code>-instance from a calendar.
     63 	 *
     64 	 * @param calendar a <code>Calendar</code>
     65 	 */
     66 	public XMPDateTimeImpl(Calendar calendar)
     67 	{
     68 		// extract the date and timezone from the calendar provided
     69         Date date = calendar.getTime();
     70         TimeZone zone = calendar.getTimeZone();
     71 
     72         // put that date into a calendar the pretty much represents ISO8601
     73         // I use US because it is close to the "locale" for the ISO8601 spec
     74         GregorianCalendar intCalendar =
     75         	(GregorianCalendar) Calendar.getInstance(Locale.US);
     76         intCalendar.setGregorianChange(new Date(Long.MIN_VALUE));
     77         intCalendar.setTimeZone(zone);
     78         intCalendar.setTime(date);
     79 
     80 		this.year = intCalendar.get(Calendar.YEAR);
     81 		this.month = intCalendar.get(Calendar.MONTH) + 1; // cal is from 0..12
     82 		this.day = intCalendar.get(Calendar.DAY_OF_MONTH);
     83 		this.hour = intCalendar.get(Calendar.HOUR_OF_DAY);
     84 		this.minute = intCalendar.get(Calendar.MINUTE);
     85 		this.second = intCalendar.get(Calendar.SECOND);
     86 		this.nanoSeconds = intCalendar.get(Calendar.MILLISECOND) * 1000000;
     87 		this.timeZone = intCalendar.getTimeZone();
     88 	}
     89 
     90 
     91 	/**
     92 	 * Creates an <code>XMPDateTime</code>-instance from
     93 	 * a <code>Date</code> and a <code>TimeZone</code>.
     94 	 *
     95 	 * @param date a date describing an absolute point in time
     96 	 * @param timeZone a TimeZone how to interpret the date
     97 	 */
     98 	public XMPDateTimeImpl(Date date, TimeZone timeZone)
     99 	{
    100 		GregorianCalendar calendar = new GregorianCalendar(timeZone);
    101 		calendar.setTime(date);
    102 		this.year = calendar.get(Calendar.YEAR);
    103 		this.month = calendar.get(Calendar.MONTH) + 1; // cal is from 0..12
    104 		this.day = calendar.get(Calendar.DAY_OF_MONTH);
    105 		this.hour = calendar.get(Calendar.HOUR_OF_DAY);
    106 		this.minute = calendar.get(Calendar.MINUTE);
    107 		this.second = calendar.get(Calendar.SECOND);
    108 		this.nanoSeconds = calendar.get(Calendar.MILLISECOND) * 1000000;
    109 		this.timeZone = timeZone;
    110 	}
    111 
    112 
    113 	/**
    114 	 * Creates an <code>XMPDateTime</code>-instance from an ISO 8601 string.
    115 	 *
    116 	 * @param strValue an ISO 8601 string
    117 	 * @throws XMPException If the string is a non-conform ISO 8601 string, an exception is thrown
    118 	 */
    119 	public XMPDateTimeImpl(String strValue) throws XMPException
    120 	{
    121 		ISO8601Converter.parse(strValue, this);
    122 	}
    123 
    124 
    125 	/**
    126 	 * @see XMPDateTime#getYear()
    127 	 */
    128 	public int getYear()
    129 	{
    130 		return year;
    131 	}
    132 
    133 
    134 	/**
    135 	 * @see XMPDateTime#setYear(int)
    136 	 */
    137 	public void setYear(int year)
    138 	{
    139 		this.year = Math.min(Math.abs(year), 9999);
    140 	}
    141 
    142 
    143 	/**
    144 	 * @see XMPDateTime#getMonth()
    145 	 */
    146 	public int getMonth()
    147 	{
    148 		return month;
    149 	}
    150 
    151 
    152 	/**
    153 	 * @see XMPDateTime#setMonth(int)
    154 	 */
    155 	public void setMonth(int month)
    156 	{
    157 		if (month < 1)
    158 		{
    159 			this.month = 1;
    160 		}
    161 		else if (month > 12)
    162 		{
    163 			this.month = 12;
    164 		}
    165 		else
    166 		{
    167 			this.month = month;
    168 		}
    169 	}
    170 
    171 
    172 	/**
    173 	 * @see XMPDateTime#getDay()
    174 	 */
    175 	public int getDay()
    176 	{
    177 		return day;
    178 	}
    179 
    180 
    181 	/**
    182 	 * @see XMPDateTime#setDay(int)
    183 	 */
    184 	public void setDay(int day)
    185 	{
    186 		if (day < 1)
    187 		{
    188 			this.day = 1;
    189 		}
    190 		else if (day > 31)
    191 		{
    192 			this.day = 31;
    193 		}
    194 		else
    195 		{
    196 			this.day = day;
    197 		}
    198 	}
    199 
    200 
    201 	/**
    202 	 * @see XMPDateTime#getHour()
    203 	 */
    204 	public int getHour()
    205 	{
    206 		return hour;
    207 	}
    208 
    209 
    210 	/**
    211 	 * @see XMPDateTime#setHour(int)
    212 	 */
    213 	public void setHour(int hour)
    214 	{
    215 		this.hour = Math.min(Math.abs(hour), 23);
    216 	}
    217 
    218 
    219 	/**
    220 	 * @see XMPDateTime#getMinute()
    221 	 */
    222 	public int getMinute()
    223 	{
    224 		return minute;
    225 	}
    226 
    227 
    228 	/**
    229 	 * @see XMPDateTime#setMinute(int)
    230 	 */
    231 	public void setMinute(int minute)
    232 	{
    233 		this.minute = Math.min(Math.abs(minute), 59);
    234 	}
    235 
    236 
    237 	/**
    238 	 * @see XMPDateTime#getSecond()
    239 	 */
    240 	public int getSecond()
    241 	{
    242 		return second;
    243 	}
    244 
    245 
    246 	/**
    247 	 * @see XMPDateTime#setSecond(int)
    248 	 */
    249 	public void setSecond(int second)
    250 	{
    251 		this.second = Math.min(Math.abs(second), 59);
    252 	}
    253 
    254 
    255 	/**
    256 	 * @see XMPDateTime#getNanoSecond()
    257 	 */
    258 	public int getNanoSecond()
    259 	{
    260 		return nanoSeconds;
    261 	}
    262 
    263 
    264 	/**
    265 	 * @see XMPDateTime#setNanoSecond(int)
    266 	 */
    267 	public void setNanoSecond(int nanoSecond)
    268 	{
    269 		this.nanoSeconds = nanoSecond;
    270 	}
    271 
    272 
    273 	/**
    274 	 * @see Comparable#compareTo(Object)
    275 	 */
    276 	public int compareTo(Object dt)
    277 	{
    278 		long d = getCalendar().getTimeInMillis()
    279 				- ((XMPDateTime) dt).getCalendar().getTimeInMillis();
    280 		if (d != 0)
    281 		{
    282 			return (int) (d % 2);
    283 		}
    284 		else
    285 		{
    286 			// if millis are equal, compare nanoseconds
    287 			d = nanoSeconds - ((XMPDateTime) dt).getNanoSecond();
    288 			return (int) (d % 2);
    289 		}
    290 	}
    291 
    292 
    293 	/**
    294 	 * @see XMPDateTime#getTimeZone()
    295 	 */
    296 	public TimeZone getTimeZone()
    297 	{
    298 		return timeZone;
    299 	}
    300 
    301 
    302 	/**
    303 	 * @see XMPDateTime#setTimeZone(TimeZone)
    304 	 */
    305 	public void setTimeZone(TimeZone timeZone)
    306 	{
    307 		this.timeZone = timeZone;
    308 	}
    309 
    310 
    311 	/**
    312 	 * @see XMPDateTime#getCalendar()
    313 	 */
    314 	public Calendar getCalendar()
    315 	{
    316 		GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance(Locale.US);
    317 		calendar.setGregorianChange(new Date(Long.MIN_VALUE));
    318 		calendar.setTimeZone(timeZone);
    319 		calendar.set(Calendar.YEAR, year);
    320 		calendar.set(Calendar.MONTH, month - 1);
    321 		calendar.set(Calendar.DAY_OF_MONTH, day);
    322 		calendar.set(Calendar.HOUR_OF_DAY, hour);
    323 		calendar.set(Calendar.MINUTE, minute);
    324 		calendar.set(Calendar.SECOND, second);
    325 		calendar.set(Calendar.MILLISECOND, nanoSeconds / 1000000);
    326 		return calendar;
    327 	}
    328 
    329 
    330 	/**
    331 	 * @see XMPDateTime#getISO8601String()
    332 	 */
    333 	public String getISO8601String()
    334 	{
    335 		return ISO8601Converter.render(this);
    336 	}
    337 
    338 
    339 	/**
    340 	 * @return Returns the ISO string representation.
    341 	 */
    342 	public String toString()
    343 	{
    344 		return getISO8601String();
    345 	}
    346 }