001    /*
002     * JBoss, Home of Professional Open Source.
003     * Copyright 2008, Red Hat Middleware LLC, and individual contributors
004     * as indicated by the @author tags. See the copyright.txt file in the
005     * distribution for a full listing of individual contributors. 
006     *
007     * This is free software; you can redistribute it and/or modify it
008     * under the terms of the GNU Lesser General Public License as
009     * published by the Free Software Foundation; either version 2.1 of
010     * the License, or (at your option) any later version.
011     *
012     * This software is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * Lesser General Public License for more details.
016     *
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this software; if not, write to the Free
019     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021     */
022    package org.jboss.dna.graph.properties.basic;
023    
024    import java.util.Calendar;
025    import java.util.Date;
026    import java.util.GregorianCalendar;
027    import java.util.Locale;
028    import java.util.concurrent.TimeUnit;
029    import net.jcip.annotations.Immutable;
030    import org.jboss.dna.common.util.CheckArg;
031    import org.joda.time.Chronology;
032    import org.joda.time.DateTime;
033    import org.joda.time.DateTimeZone;
034    
035    /**
036     * Implementation of DateTime based upon the Joda-Time library.
037     * 
038     * @author Randall Hauch
039     */
040    @Immutable
041    public class JodaDateTime implements org.jboss.dna.graph.properties.DateTime {
042    
043        /**
044         */
045        private static final long serialVersionUID = -730188225988292422L;
046    
047        private static final int MILLIS_IN_HOUR = 1000 * 60 * 60;
048    
049        private final DateTime instance;
050        private transient String formattedString;
051    
052        public JodaDateTime() {
053            this.instance = new DateTime();
054        }
055    
056        public JodaDateTime( String iso8601 ) {
057            this.instance = new DateTime(iso8601);
058        }
059    
060        public JodaDateTime( String iso8601,
061                             String timeZoneId ) {
062            this.instance = new DateTime(iso8601, DateTimeZone.forID(timeZoneId));
063        }
064    
065        public JodaDateTime( long milliseconds ) {
066            this.instance = new DateTime(milliseconds);
067        }
068    
069        public JodaDateTime( long milliseconds,
070                             Chronology chronology ) {
071            this.instance = new DateTime(milliseconds, chronology);
072        }
073    
074        public JodaDateTime( long milliseconds,
075                             String timeZoneId ) {
076            this.instance = new DateTime(milliseconds, DateTimeZone.forID(timeZoneId));
077        }
078    
079        public JodaDateTime( DateTimeZone dateTimeZone ) {
080            this.instance = new DateTime(dateTimeZone);
081        }
082    
083        public JodaDateTime( int year,
084                             int monthOfYear,
085                             int dayOfMonth,
086                             int hourOfDay,
087                             int minuteOfHour,
088                             int secondOfMinute,
089                             int millisecondsOfSecond ) {
090            this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisecondsOfSecond);
091        }
092    
093        public JodaDateTime( int year,
094                             int monthOfYear,
095                             int dayOfMonth,
096                             int hourOfDay,
097                             int minuteOfHour,
098                             int secondOfMinute,
099                             int millisecondsOfSecond,
100                             Chronology chronology ) {
101            this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
102                                         millisecondsOfSecond, chronology);
103        }
104    
105        public JodaDateTime( int year,
106                             int monthOfYear,
107                             int dayOfMonth,
108                             int hourOfDay,
109                             int minuteOfHour,
110                             int secondOfMinute,
111                             int millisecondsOfSecond,
112                             DateTimeZone dateTimeZone ) {
113            this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
114                                         millisecondsOfSecond, dateTimeZone);
115        }
116    
117        public JodaDateTime( int year,
118                             int monthOfYear,
119                             int dayOfMonth,
120                             int hourOfDay,
121                             int minuteOfHour,
122                             int secondOfMinute,
123                             int millisecondsOfSecond,
124                             int timeZoneOffsetHours ) {
125            this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
126                                         millisecondsOfSecond, DateTimeZone.forOffsetHours(timeZoneOffsetHours));
127        }
128    
129        public JodaDateTime( int year,
130                             int monthOfYear,
131                             int dayOfMonth,
132                             int hourOfDay,
133                             int minuteOfHour,
134                             int secondOfMinute,
135                             int millisecondsOfSecond,
136                             String timeZoneId ) {
137            this.instance = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
138                                         millisecondsOfSecond, DateTimeZone.forID(timeZoneId));
139        }
140    
141        public JodaDateTime( java.util.Date jdkDate ) {
142            this.instance = new DateTime(jdkDate);
143        }
144    
145        public JodaDateTime( java.util.Calendar jdkCalendar ) {
146            this.instance = new DateTime(jdkCalendar);
147        }
148    
149        public JodaDateTime( DateTime dateTime ) {
150            this.instance = dateTime; // it's immutable, so just hold onto the supplied instance
151        }
152    
153        /**
154         * {@inheritDoc}
155         */
156        public int getCenturyOfEra() {
157            return this.instance.getCenturyOfEra();
158        }
159    
160        /**
161         * {@inheritDoc}
162         */
163        public int getDayOfMonth() {
164            return this.instance.getDayOfMonth();
165        }
166    
167        /**
168         * {@inheritDoc}
169         */
170        public int getDayOfWeek() {
171            return this.instance.getDayOfWeek();
172        }
173    
174        /**
175         * {@inheritDoc}
176         */
177        public int getDayOfYear() {
178            return this.instance.getDayOfYear();
179        }
180    
181        /**
182         * {@inheritDoc}
183         */
184        public int getEra() {
185            return this.instance.getEra();
186        }
187    
188        /**
189         * {@inheritDoc}
190         */
191        public int getHourOfDay() {
192            return this.instance.getHourOfDay();
193        }
194    
195        /**
196         * {@inheritDoc}
197         */
198        public int getMillisOfSecond() {
199            return this.instance.getMillisOfSecond();
200        }
201    
202        /**
203         * {@inheritDoc}
204         */
205        public long getMilliseconds() {
206            return this.instance.getMillis();
207        }
208    
209        /**
210         * {@inheritDoc}
211         */
212        public int getMinuteOfHour() {
213            return this.instance.getMinuteOfHour();
214        }
215    
216        /**
217         * {@inheritDoc}
218         */
219        public int getMonthOfYear() {
220            return this.instance.getMonthOfYear();
221        }
222    
223        /**
224         * {@inheritDoc}
225         */
226        public int getSecondOfMinute() {
227            return this.instance.getSecondOfMinute();
228        }
229    
230        /**
231         * {@inheritDoc}
232         */
233        public String getString() {
234            if (this.formattedString == null) {
235                // This is transient and can be done multiple times by concurrent threads (without locking),
236                // since the object is immutable
237                this.formattedString = this.instance.toString(org.joda.time.format.ISODateTimeFormat.dateTime());
238            }
239            return this.formattedString;
240        }
241    
242        /**
243         * {@inheritDoc}
244         */
245        public int getWeekOfWeekyear() {
246            return this.instance.getWeekOfWeekyear();
247        }
248    
249        /**
250         * {@inheritDoc}
251         */
252        public int getWeekyear() {
253            return this.instance.getWeekyear();
254        }
255    
256        /**
257         * {@inheritDoc}
258         */
259        public int getYear() {
260            return this.instance.getYear();
261        }
262    
263        /**
264         * {@inheritDoc}
265         */
266        public int getYearOfCentury() {
267            return this.instance.getYearOfCentury();
268        }
269    
270        /**
271         * {@inheritDoc}
272         */
273        public int getYearOfEra() {
274            return this.instance.getYearOfEra();
275        }
276    
277        /**
278         * {@inheritDoc}
279         */
280        public int getTimeZoneOffsetHours() {
281            // return this.instance.getZone().toTimeZone().getRawOffset() / MILLIS_IN_HOUR;
282            return this.instance.getZone().getOffset(this.instance.getMillis()) / MILLIS_IN_HOUR;
283        }
284    
285        /**
286         * {@inheritDoc}
287         */
288        public String getTimeZoneId() {
289            return this.instance.getZone().getID();
290        }
291    
292        /**
293         * {@inheritDoc}
294         */
295        public Calendar toCalendar() {
296            return toCalendar(null);
297        }
298    
299        /**
300         * {@inheritDoc}
301         */
302        public Calendar toCalendar( Locale locale ) {
303            return this.instance.toCalendar(locale);
304        }
305    
306        /**
307         * {@inheritDoc}
308         */
309        public Date toDate() {
310            return this.instance.toDate();
311        }
312    
313        /**
314         * {@inheritDoc}
315         */
316        public GregorianCalendar toGregorianCalendar() {
317            return this.instance.toGregorianCalendar();
318        }
319    
320        /**
321         * {@inheritDoc}
322         */
323        public int compareTo( org.jboss.dna.graph.properties.DateTime that ) {
324            if (that instanceof JodaDateTime) {
325                return this.instance.compareTo(((JodaDateTime)that).instance);
326            }
327            long diff = this.toUtcTimeZone().getMilliseconds() - that.toUtcTimeZone().getMilliseconds();
328            return (int)diff;
329        }
330    
331        /**
332         * {@inheritDoc}
333         */
334        @Override
335        public int hashCode() {
336            return this.instance.hashCode();
337        }
338    
339        /**
340         * {@inheritDoc}
341         */
342        @Override
343        public boolean equals( Object obj ) {
344            if (obj == this) return true;
345            if (obj instanceof JodaDateTime) {
346                JodaDateTime that = (JodaDateTime)obj;
347                return this.instance.equals(that.instance);
348            }
349            if (obj instanceof DateTime) {
350                return this.instance.equals(obj);
351            }
352            return false;
353        }
354    
355        /**
356         * {@inheritDoc}
357         */
358        @Override
359        public String toString() {
360            return getString();
361        }
362    
363        /**
364         * {@inheritDoc}
365         */
366        public org.jboss.dna.graph.properties.DateTime toUtcTimeZone() {
367            DateTime jodaTime = this.instance.withZone(DateTimeZone.forID("UTC"));
368            return new JodaDateTime(jodaTime);
369        }
370    
371        /**
372         * {@inheritDoc}
373         */
374        public org.jboss.dna.graph.properties.DateTime toTimeZone( String timeZoneId ) {
375            CheckArg.isNotNull(timeZoneId, "time zone identifier");
376            DateTime jodaTime = this.instance.withZone(DateTimeZone.forID(timeZoneId));
377            return new JodaDateTime(jodaTime);
378        }
379    
380        /**
381         * {@inheritDoc}
382         * 
383         * @see org.jboss.dna.graph.properties.DateTime#isBefore(org.jboss.dna.graph.properties.DateTime)
384         */
385        public boolean isBefore( org.jboss.dna.graph.properties.DateTime other ) {
386            return this.compareTo(other) < 0;
387        }
388    
389        /**
390         * {@inheritDoc}
391         * 
392         * @see org.jboss.dna.graph.properties.DateTime#isSameAs(org.jboss.dna.graph.properties.DateTime)
393         */
394        public boolean isSameAs( org.jboss.dna.graph.properties.DateTime other ) {
395            return this.compareTo(other) == 0;
396        }
397    
398        /**
399         * {@inheritDoc}
400         * 
401         * @see org.jboss.dna.graph.properties.DateTime#isAfter(org.jboss.dna.graph.properties.DateTime)
402         */
403        public boolean isAfter( org.jboss.dna.graph.properties.DateTime other ) {
404            return this.compareTo(other) > 0;
405        }
406    
407        /**
408         * {@inheritDoc}
409         * 
410         * @see org.jboss.dna.graph.properties.DateTime#minus(long, java.util.concurrent.TimeUnit)
411         */
412        public org.jboss.dna.graph.properties.DateTime minus( long timeAmount,
413                                                       TimeUnit unit ) {
414            CheckArg.isNotNull(unit, "unit");
415            return new JodaDateTime(this.instance.minus(TimeUnit.MILLISECONDS.convert(timeAmount, unit)));
416        }
417    
418        /**
419         * {@inheritDoc}
420         * 
421         * @see org.jboss.dna.graph.properties.DateTime#minusDays(int)
422         */
423        public org.jboss.dna.graph.properties.DateTime minusDays( int days ) {
424            return new JodaDateTime(this.instance.minusDays(days));
425        }
426    
427        /**
428         * {@inheritDoc}
429         * 
430         * @see org.jboss.dna.graph.properties.DateTime#minusHours(int)
431         */
432        public org.jboss.dna.graph.properties.DateTime minusHours( int hours ) {
433            return new JodaDateTime(this.instance.minusHours(hours));
434        }
435    
436        /**
437         * {@inheritDoc}
438         * 
439         * @see org.jboss.dna.graph.properties.DateTime#minusMillis(int)
440         */
441        public org.jboss.dna.graph.properties.DateTime minusMillis( int milliseconds ) {
442            return new JodaDateTime(this.instance.minusMillis(milliseconds));
443        }
444    
445        /**
446         * {@inheritDoc}
447         * 
448         * @see org.jboss.dna.graph.properties.DateTime#minusMinutes(int)
449         */
450        public org.jboss.dna.graph.properties.DateTime minusMinutes( int minutes ) {
451            return new JodaDateTime(this.instance.minusMinutes(minutes));
452        }
453    
454        /**
455         * {@inheritDoc}
456         * 
457         * @see org.jboss.dna.graph.properties.DateTime#minusMonths(int)
458         */
459        public org.jboss.dna.graph.properties.DateTime minusMonths( int months ) {
460            return new JodaDateTime(this.instance.minusMonths(months));
461        }
462    
463        /**
464         * {@inheritDoc}
465         * 
466         * @see org.jboss.dna.graph.properties.DateTime#minusSeconds(int)
467         */
468        public org.jboss.dna.graph.properties.DateTime minusSeconds( int seconds ) {
469            return new JodaDateTime(this.instance.minusSeconds(seconds));
470        }
471    
472        /**
473         * {@inheritDoc}
474         * 
475         * @see org.jboss.dna.graph.properties.DateTime#minusWeeks(int)
476         */
477        public org.jboss.dna.graph.properties.DateTime minusWeeks( int weeks ) {
478            return new JodaDateTime(this.instance.minusWeeks(weeks));
479        }
480    
481        /**
482         * {@inheritDoc}
483         * 
484         * @see org.jboss.dna.graph.properties.DateTime#minusYears(int)
485         */
486        public org.jboss.dna.graph.properties.DateTime minusYears( int years ) {
487            return new JodaDateTime(this.instance.minusYears(years));
488        }
489    
490        /**
491         * {@inheritDoc}
492         * 
493         * @see org.jboss.dna.graph.properties.DateTime#plus(long, java.util.concurrent.TimeUnit)
494         */
495        public org.jboss.dna.graph.properties.DateTime plus( long timeAmount,
496                                                      TimeUnit unit ) {
497            CheckArg.isNotNull(unit, "unit");
498            return new JodaDateTime(this.instance.plus(TimeUnit.MILLISECONDS.convert(timeAmount, unit)));
499        }
500    
501        /**
502         * {@inheritDoc}
503         * 
504         * @see org.jboss.dna.graph.properties.DateTime#plusDays(int)
505         */
506        public org.jboss.dna.graph.properties.DateTime plusDays( int days ) {
507            return new JodaDateTime(this.instance.plusDays(days));
508        }
509    
510        /**
511         * {@inheritDoc}
512         * 
513         * @see org.jboss.dna.graph.properties.DateTime#plusHours(int)
514         */
515        public org.jboss.dna.graph.properties.DateTime plusHours( int hours ) {
516            return new JodaDateTime(this.instance.plusHours(hours));
517        }
518    
519        /**
520         * {@inheritDoc}
521         * 
522         * @see org.jboss.dna.graph.properties.DateTime#plusMillis(int)
523         */
524        public org.jboss.dna.graph.properties.DateTime plusMillis( int milliseconds ) {
525            return new JodaDateTime(this.instance.plusMillis(milliseconds));
526        }
527    
528        /**
529         * {@inheritDoc}
530         * 
531         * @see org.jboss.dna.graph.properties.DateTime#plusMinutes(int)
532         */
533        public org.jboss.dna.graph.properties.DateTime plusMinutes( int minutes ) {
534            return new JodaDateTime(this.instance.plusMinutes(minutes));
535        }
536    
537        /**
538         * {@inheritDoc}
539         * 
540         * @see org.jboss.dna.graph.properties.DateTime#plusMonths(int)
541         */
542        public org.jboss.dna.graph.properties.DateTime plusMonths( int months ) {
543            return new JodaDateTime(this.instance.plusMonths(months));
544        }
545    
546        /**
547         * {@inheritDoc}
548         * 
549         * @see org.jboss.dna.graph.properties.DateTime#plusSeconds(int)
550         */
551        public org.jboss.dna.graph.properties.DateTime plusSeconds( int seconds ) {
552            return new JodaDateTime(this.instance.plusSeconds(seconds));
553        }
554    
555        /**
556         * {@inheritDoc}
557         * 
558         * @see org.jboss.dna.graph.properties.DateTime#plusWeeks(int)
559         */
560        public org.jboss.dna.graph.properties.DateTime plusWeeks( int weeks ) {
561            return new JodaDateTime(this.instance.plusWeeks(weeks));
562        }
563    
564        /**
565         * {@inheritDoc}
566         * 
567         * @see org.jboss.dna.graph.properties.DateTime#plusYears(int)
568         */
569        public org.jboss.dna.graph.properties.DateTime plusYears( int years ) {
570            return new JodaDateTime(this.instance.plusYears(years));
571        }
572    
573    }