Source Code Cross Referenced for CalendarImpl.java in  » 6.0-JDK-Modules » j2me » com » sun » cldc » util » j2me » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.cldc.util.j2me 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *   
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         */
026:
027:        package com.sun.cldc.util.j2me;
028:
029:        import java.util.*;
030:        import java.io.*;
031:
032:        /**
033:         * This class is an implementation of the subsetted
034:         * CLDC 1.1 Calendar class.
035:         *
036:         * @see java.util.Calendar
037:         * @see java.util.TimeZone
038:         */
039:        public class CalendarImpl extends Calendar {
040:
041:            /* ERA */
042:            private static final int BC = 0;
043:            private static final int AD = 1;
044:
045:            /* January 1, year 1 (Gregorian) */
046:            private static final int JAN_1_1_JULIAN_DAY = 1721426;
047:
048:            /* January 1, 1970 (Gregorian) */
049:            private static final int EPOCH_JULIAN_DAY = 2440588;
050:
051:            /* 0-based, for day-in-year */
052:            private static final int NUM_DAYS[] = { 0, 31, 59, 90, 120, 151,
053:                    181, 212, 243, 273, 304, 334 };
054:
055:            /* 0-based, for day-in-year */
056:            private static final int LEAP_NUM_DAYS[] = { 0, 31, 60, 91, 121,
057:                    152, 182, 213, 244, 274, 305, 335 };
058:
059:            /**
060:             * Useful millisecond constants.  Although ONE_DAY and ONE_WEEK can fit
061:             * into ints, they must be longs in order to prevent arithmetic overflow
062:             * when performing (CR 4173516).
063:             */
064:            private static final int ONE_SECOND = 1000;
065:            private static final int ONE_MINUTE = 60 * ONE_SECOND;
066:            private static final int ONE_HOUR = 60 * ONE_MINUTE;
067:            private static final long ONE_DAY = 24 * ONE_HOUR;
068:
069:            /**
070:             * The point at which the Gregorian calendar rules are used, measured in
071:             * milliseconds from the standard epoch.  Default is October 15, 1582
072:             * (Gregorian) 00:00:00 UTC or -12219292800000L.  For this value, October 4,
073:             * 1582 (Julian) is followed by October 15, 1582 (Gregorian).  This
074:             * corresponds to Julian day number 2299161.
075:             */
076:            private static final long gregorianCutover = -12219292800000L;
077:
078:            /**
079:             * The year of the gregorianCutover, with 0 representing
080:             * 1 BC, -1 representing 2 BC, etc.
081:             */
082:            private static final int gregorianCutoverYear = 1582;
083:
084:            public CalendarImpl() {
085:                super ();
086:            }
087:
088:            /**
089:             * Converts UTC as milliseconds to time field values.
090:             */
091:            protected void computeFields() {
092:                int rawOffset = getTimeZone().getRawOffset();
093:                long localMillis = time + rawOffset;
094:
095:                // Check for very extreme values -- millis near Long.MIN_VALUE or
096:                // Long.MAX_VALUE.  For these values, adding the zone offset can push
097:                // the millis past MAX_VALUE to MIN_VALUE, or vice versa.  This produces
098:                // the undesirable effect that the time can wrap around at the ends,
099:                // yielding, for example, a Date(Long.MAX_VALUE) with a big BC year
100:                // (should be AD).  Handle this by pinning such values to Long.MIN_VALUE
101:                // or Long.MAX_VALUE. - liu 8/11/98 CR 4149677
102:                if (time > 0 && localMillis < 0 && rawOffset > 0) {
103:                    localMillis = Long.MAX_VALUE;
104:                } else if (time < 0 && localMillis > 0 && rawOffset < 0) {
105:                    localMillis = Long.MIN_VALUE;
106:                }
107:
108:                // Time to fields takes the wall millis (Standard or DST).
109:                timeToFields(localMillis);
110:
111:                long days = (long) (localMillis / ONE_DAY);
112:                int millisInDay = (int) (localMillis - (days * ONE_DAY));
113:
114:                if (millisInDay < 0)
115:                    millisInDay += ONE_DAY;
116:
117:                // Call getOffset() to get the TimeZone offset.
118:                // The millisInDay value must be standard local millis.
119:                int dstOffset = getTimeZone().getOffset(AD, this .fields[YEAR],
120:                        this .fields[MONTH], this .fields[DATE],
121:                        this .fields[DAY_OF_WEEK], millisInDay)
122:                        - rawOffset;
123:
124:                // Adjust our millisInDay for DST, if necessary.
125:                millisInDay += dstOffset;
126:
127:                // If DST has pushed us into the next day,
128:                // we must call timeToFields() again.
129:                // This happens in DST between 12:00 am and 1:00 am every day.
130:                // The call to timeToFields() will give the wrong day,
131:                // since the Standard time is in the previous day
132:                if (millisInDay >= ONE_DAY) {
133:                    long dstMillis = localMillis + dstOffset;
134:                    millisInDay -= ONE_DAY;
135:                    // As above, check for and pin extreme values
136:                    if (localMillis > 0 && dstMillis < 0 && dstOffset > 0) {
137:                        dstMillis = Long.MAX_VALUE;
138:                    } else if (localMillis < 0 && dstMillis > 0
139:                            && dstOffset < 0) {
140:                        dstMillis = Long.MIN_VALUE;
141:                    }
142:                    timeToFields(dstMillis);
143:                }
144:
145:                // Fill in all time-related fields based on millisInDay.
146:                // so as not to perturb flags.
147:                this .fields[MILLISECOND] = millisInDay % 1000;
148:                millisInDay /= 1000;
149:
150:                this .fields[SECOND] = millisInDay % 60;
151:                millisInDay /= 60;
152:
153:                this .fields[MINUTE] = millisInDay % 60;
154:                millisInDay /= 60;
155:
156:                this .fields[HOUR_OF_DAY] = millisInDay;
157:                this .fields[AM_PM] = millisInDay / 12;
158:                this .fields[HOUR] = millisInDay % 12;
159:            }
160:
161:            /**
162:             * Convert the time as milliseconds to the date fields.  Millis must be
163:             * given as local wall millis to get the correct local day.  For example,
164:             * if it is 11:30 pm Standard, and DST is in effect, the correct DST millis
165:             * must be passed in to get the right date.
166:             * <p>
167:             * Fields that are completed by this method: YEAR, MONTH, DATE, DAY_OF_WEEK.
168:             * @param theTime the time in wall millis (either Standard or DST),
169:             * whichever is in effect
170:             */
171:            private final void timeToFields(long theTime) {
172:                int dayOfYear, weekCount, rawYear;
173:                boolean isLeap;
174:
175:                // Compute the year, month, and day of month from the given millis
176:                if (theTime >= gregorianCutover) {
177:
178:                    // The Gregorian epoch day is zero for Monday January 1, year 1.
179:                    long gregorianEpochDay = millisToJulianDay(theTime)
180:                            - JAN_1_1_JULIAN_DAY;
181:
182:                    // Here we convert from the day number to the multiple radix
183:                    // representation.  We use 400-year, 100-year, and 4-year cycles.
184:                    // For example, the 4-year cycle has 4 years + 1 leap day; giving
185:                    // 1461 == 365*4 + 1 days.
186:                    int[] rem = new int[1];
187:
188:                    // 400-year cycle length
189:                    int n400 = floorDivide(gregorianEpochDay, 146097, rem);
190:
191:                    // 100-year cycle length
192:                    int n100 = floorDivide(rem[0], 36524, rem);
193:
194:                    // 4-year cycle length
195:                    int n4 = floorDivide(rem[0], 1461, rem);
196:
197:                    int n1 = floorDivide(rem[0], 365, rem);
198:                    rawYear = 400 * n400 + 100 * n100 + 4 * n4 + n1;
199:
200:                    // zero-based day of year
201:                    dayOfYear = rem[0];
202:
203:                    // Dec 31 at end of 4- or 400-yr cycle
204:                    if (n100 == 4 || n1 == 4) {
205:                        dayOfYear = 365;
206:                    } else {
207:                        ++rawYear;
208:                    }
209:
210:                    // equiv. to (rawYear%4 == 0)
211:                    isLeap = ((rawYear & 0x3) == 0)
212:                            && (rawYear % 100 != 0 || rawYear % 400 == 0);
213:
214:                    // Gregorian day zero is a Monday
215:                    this .fields[DAY_OF_WEEK] = (int) ((gregorianEpochDay + 1) % 7);
216:                } else {
217:                    // The Julian epoch day (not the same as Julian Day)
218:                    // is zero on Saturday December 30, 0 (Gregorian).
219:                    long julianEpochDay = millisToJulianDay(theTime)
220:                            - (JAN_1_1_JULIAN_DAY - 2);
221:
222:                    rawYear = (int) floorDivide(4 * julianEpochDay + 1464, 1461);
223:
224:                    // Compute the Julian calendar day number for January 1, year
225:                    long january1 = 365 * (rawYear - 1)
226:                            + floorDivide(rawYear - 1, 4);
227:                    dayOfYear = (int) (julianEpochDay - january1); // 0-based
228:
229:                    // Julian leap years occurred historically every 4 years starting
230:                    // with 8 AD.  Before 8 AD the spacing is irregular; every 3 years
231:                    // from 45 BC to 9 BC, and then none until 8 AD.  However, we don't
232:                    // implement this historical detail; instead, we implement the
233:                    // computationally cleaner proleptic calendar, which assumes
234:                    // consistent 4-year cycles throughout time.
235:
236:                    // equiv. to (rawYear%4 == 0)
237:                    isLeap = ((rawYear & 0x3) == 0);
238:
239:                    // Julian calendar day zero is a Saturday
240:                    this .fields[DAY_OF_WEEK] = (int) ((julianEpochDay - 1) % 7);
241:                }
242:
243:                // Common Julian/Gregorian calculation
244:                int correction = 0;
245:
246:                // zero-based DOY for March 1
247:                int march1 = isLeap ? 60 : 59;
248:
249:                if (dayOfYear >= march1)
250:                    correction = isLeap ? 1 : 2;
251:
252:                // zero-based month
253:                int month_field = (12 * (dayOfYear + correction) + 6) / 367;
254:
255:                // one-based DOM
256:                int date_field = dayOfYear
257:                        - (isLeap ? LEAP_NUM_DAYS[month_field]
258:                                : NUM_DAYS[month_field]) + 1;
259:
260:                // Normalize day of week
261:                this .fields[DAY_OF_WEEK] += (this .fields[DAY_OF_WEEK] < 0) ? (SUNDAY + 7)
262:                        : SUNDAY;
263:
264:                this .fields[YEAR] = rawYear;
265:
266:                // If year is < 1 we are in BC
267:                if (this .fields[YEAR] < 1) {
268:                    this .fields[YEAR] = 1 - this .fields[YEAR];
269:                }
270:
271:                // 0-based
272:                this .fields[MONTH] = month_field + JANUARY;
273:                this .fields[DATE] = date_field;
274:            }
275:
276:            /*
277:             * The following two static arrays are used privately by the
278:             * <code>toString(Calendar calendar)</code> function below.
279:             */
280:            static String[] months = { "Jan", "Feb", "Mar", "Apr", "May",
281:                    "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
282:
283:            static String[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
284:                    "Sat" };
285:
286:            /**
287:             * Converts this <code>Date</code> object to a <code>String</code>
288:             * of the form:
289:             * <blockquote><pre>
290:             * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
291:             * where:<ul>
292:             * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
293:             *     Thu, Fri, Sat</tt>).
294:             * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
295:             *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
296:             * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
297:             *     <tt>31</tt>), as two decimal digits.
298:             * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
299:             *     <tt>23</tt>), as two decimal digits.
300:             * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
301:             *     <tt>59</tt>), as two decimal digits.
302:             * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
303:             *     <tt>61</tt>, as two decimal digits.
304:             * <li><tt>zzz</tt> is the time zone (and may reflect daylight savings
305:             *     time). If time zone information is not available,
306:             *     then <tt>zzz</tt> is empty - that is, it consists
307:             *     of no characters at all.
308:             * <li><tt>yyyy</tt> is the year, as four decimal digits.
309:             * </ul>
310:             *
311:             * @return  a string representation of this date.
312:             */
313:            public static String toString(Calendar calendar) {
314:                // Printing in the absence of a Calendar
315:                // implementation class is not supported
316:                if (calendar == null) {
317:                    return "Thu Jan 01 00:00:00 UTC 1970";
318:                }
319:
320:                int dow = calendar.get(Calendar.DAY_OF_WEEK);
321:                int month = calendar.get(Calendar.MONTH);
322:                int day = calendar.get(Calendar.DAY_OF_MONTH);
323:                int hour_of_day = calendar.get(Calendar.HOUR_OF_DAY);
324:                int minute = calendar.get(Calendar.MINUTE);
325:                int seconds = calendar.get(Calendar.SECOND);
326:                int year = calendar.get(Calendar.YEAR);
327:
328:                String yr = Integer.toString(year);
329:
330:                TimeZone zone = calendar.getTimeZone();
331:                String zoneID = zone.getID();
332:                if (zoneID == null)
333:                    zoneID = "";
334:
335:                // The total size of the string buffer
336:                // 3+1+3+1+2+1+2+1+2+1+2+1+zoneID.length+1+yr.length
337:                //  = 21 + zoneID.length + yr.length
338:                StringBuffer sb = new StringBuffer(25 + zoneID.length()
339:                        + yr.length());
340:
341:                sb.append(days[dow - 1]).append(' ');
342:                sb.append(months[month]).append(' ');
343:                appendTwoDigits(sb, day).append(' ');
344:                appendTwoDigits(sb, hour_of_day).append(':');
345:                appendTwoDigits(sb, minute).append(':');
346:                appendTwoDigits(sb, seconds).append(' ');
347:                if (zoneID.length() > 0)
348:                    sb.append(zoneID).append(' ');
349:                appendFourDigits(sb, year);
350:
351:                return sb.toString();
352:            }
353:
354:            /**
355:             * Converts this <code>Date</code> object to a <code>String</code>.
356:             * The output format is as follows:
357:             * <blockquote><pre>yyyy MM dd hh mm ss +zzzz</pre></blockquote>
358:             * where:<ul>
359:             * <li><dd>yyyy</dd> is the year, as four decimal digits.
360:             *    Year values larger than <dd>9999</dd> will be truncated
361:             *    to <dd>9999</dd>.
362:             * <li><dd>MM</dd> is the month (<dd>01</dd> through <dd>12</dd>),
363:             *    as two decimal digits.
364:             * <li><dd>dd</dd> is the day of the month (<dd>01</dd> through
365:             *    <dd>31</dd>), as two decimal digits.
366:             * <li><dd>hh</dd> is the hour of the day (<dd>00</dd> through
367:             *    <dd>23</dd>), as two decimal digits.
368:             * <li><dd>mm</dd> is the minute within the hour (<dd>00</dd>
369:             *     through <dd>59</dd>), as two decimal digits.
370:             * <li><dd>ss</dd> is the second within the minute (<dd>00</dd>
371:             *    through <dd>59</dd>), as two decimal digits.
372:             * <li><dd>zzzz</dd> is the time zone offset in hours and minutes
373:             *      (four decimal digits <dd>"hhmm"</dd>) relative to GMT,
374:             *      preceded by a "+" or "-" character (<dd>-1200</dd>
375:             *      through <dd>+1200</dd>).
376:             *      For instance, Pacific Standard Time zone is printed
377:             *      as <dd>-0800</dd>.  GMT is printed as <dd>+0000</dd>.
378:             * </ul>
379:             *
380:             * @return  a string representation of this date.
381:             */
382:            public static String toISO8601String(Calendar calendar) {
383:                // Printing in the absence of a Calendar
384:                // implementation class is not supported
385:                if (calendar == null) {
386:                    return "0000 00 00 00 00 00 +0000";
387:                }
388:
389:                int year = calendar.get(Calendar.YEAR);
390:                int month = calendar.get(Calendar.MONTH) + 1;
391:                int day = calendar.get(Calendar.DAY_OF_MONTH);
392:                int hour_of_day = calendar.get(Calendar.HOUR_OF_DAY);
393:                int hour = calendar.get(Calendar.HOUR);
394:                int minute = calendar.get(Calendar.MINUTE);
395:                int seconds = calendar.get(Calendar.SECOND);
396:
397:                String yr = Integer.toString(year);
398:
399:                // The total size of the string buffer
400:                // yr.length+1+2+1+2+1+2+1+2+1+2+1+5 = 25 + yr.length
401:                StringBuffer sb = new StringBuffer(25 + yr.length());
402:
403:                appendFourDigits(sb, year).append(' ');
404:                appendTwoDigits(sb, month).append(' ');
405:                appendTwoDigits(sb, day).append(' ');
406:                appendTwoDigits(sb, hour_of_day).append(' ');
407:                appendTwoDigits(sb, minute).append(' ');
408:                appendTwoDigits(sb, seconds).append(' ');
409:
410:                // TimeZone offset is represented in milliseconds.
411:                // Convert the offset to minutes:
412:                TimeZone t = calendar.getTimeZone();
413:                int zoneOffsetInMinutes = t.getRawOffset() / 1000 / 60;
414:
415:                if (zoneOffsetInMinutes < 0) {
416:                    zoneOffsetInMinutes = Math.abs(zoneOffsetInMinutes);
417:                    sb.append('-');
418:                } else {
419:                    sb.append('+');
420:                }
421:
422:                int zoneHours = zoneOffsetInMinutes / 60;
423:                int zoneMinutes = zoneOffsetInMinutes % 60;
424:
425:                appendTwoDigits(sb, zoneHours);
426:                appendTwoDigits(sb, zoneMinutes);
427:
428:                return sb.toString();
429:            }
430:
431:            private static final StringBuffer appendFourDigits(StringBuffer sb,
432:                    int number) {
433:                if (number >= 0 && number < 1000) {
434:                    sb.append('0');
435:                    if (number < 100) {
436:                        sb.append('0');
437:                    }
438:                    if (number < 10) {
439:                        sb.append('0');
440:                    }
441:                }
442:                return sb.append(number);
443:            }
444:
445:            private static final StringBuffer appendTwoDigits(StringBuffer sb,
446:                    int number) {
447:                if (number < 10) {
448:                    sb.append('0');
449:                }
450:                return sb.append(number);
451:            }
452:
453:            /////////////////////////////
454:            // Fields => Time computation
455:            /////////////////////////////
456:
457:            /**
458:             * Converts time field values to UTC as milliseconds.
459:             * @exception IllegalArgumentException if any fields are invalid.
460:             */
461:            protected void computeTime() {
462:
463:                correctTime();
464:
465:                // This function takes advantage of the fact that unset fields in
466:                // the time field list have a value of zero.
467:
468:                // First, use the year to determine whether to use the Gregorian or the
469:                // Julian calendar. If the year is not the year of the cutover, this
470:                // computation will be correct. But if the year is the cutover year,
471:                // this may be incorrect. In that case, assume the Gregorian calendar,
472:                // make the computation, and then recompute if the resultant millis
473:                // indicate the wrong calendar has been assumed.
474:
475:                // A date such as Oct. 10, 1582 does not exist in a Gregorian calendar
476:                // with the default changeover of Oct. 15, 1582, since in such a
477:                // calendar Oct. 4 (Julian) is followed by Oct. 15 (Gregorian).  This
478:                // algorithm will interpret such a date using the Julian calendar,
479:                // yielding Oct. 20, 1582 (Gregorian).
480:                int year = this .fields[YEAR];
481:                boolean isGregorian = year >= gregorianCutoverYear;
482:                long julianDay = calculateJulianDay(isGregorian, year);
483:                long millis = julianDayToMillis(julianDay);
484:
485:                // The following check handles portions of the cutover year BEFORE the
486:                // cutover itself happens. The check for the julianDate number is for a
487:                // rare case; it's a hardcoded number, but it's efficient.  The given
488:                // Julian day number corresponds to Dec 3, 292269055 BC, which
489:                // corresponds to millis near Long.MIN_VALUE.  The need for the check
490:                // arises because for extremely negative Julian day numbers, the millis
491:                // actually overflow to be positive values. Without the check, the
492:                // initial date is interpreted with the Gregorian calendar, even when
493:                // the cutover doesn't warrant it.
494:                if (isGregorian != (millis >= gregorianCutover)
495:                        && julianDay != -106749550580L) { // See above
496:
497:                    julianDay = calculateJulianDay(!isGregorian, year);
498:                    millis = julianDayToMillis(julianDay);
499:                }
500:
501:                // Do the time portion of the conversion.
502:
503:                int millisInDay = 0;
504:
505:                // Hours
506:                // Don't normalize here; let overflow bump into the next period.
507:                // This is consistent with how we handle other fields.
508:                millisInDay += this .fields[HOUR_OF_DAY];
509:                millisInDay *= 60;
510:
511:                // now get minutes
512:                millisInDay += this .fields[MINUTE];
513:                millisInDay *= 60;
514:
515:                // now get seconds
516:                millisInDay += this .fields[SECOND];
517:                millisInDay *= 1000;
518:
519:                // now get millis
520:                millisInDay += this .fields[MILLISECOND];
521:
522:                // Compute the time zone offset and DST offset.  There are two potential
523:                // ambiguities here.  We'll assume a 2:00 am (wall time) switchover time
524:                // for discussion purposes here.
525:                // 1. The transition into DST.  Here, a designated time of 2:00 am - 2:59 am
526:                //    can be in standard or in DST depending.  However, 2:00 am is an invalid
527:                //    representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
528:                //    We assume standard time.
529:                // 2. The transition out of DST.  Here, a designated time of 1:00 am - 1:59 am
530:                //    can be in standard or DST.  Both are valid representations (the rep
531:                //    jumps from 1:59:59 DST to 1:00:00 Std).
532:                //    Again, we assume standard time.
533:                // We use the TimeZone object to get the zone offset
534:                int zoneOffset = getTimeZone().getRawOffset();
535:
536:                // Now add date and millisInDay together, to make millis contain local wall
537:                // millis, with no zone or DST adjustments
538:                millis += millisInDay;
539:
540:                // Normalize the millisInDay to 0..ONE_DAY-1.  If the millis is out
541:                // of range, then we must call timeToFields() to recompute our
542:                // fields.
543:                int[] normalizedMillisInDay = new int[1];
544:                floorDivide(millis, (int) ONE_DAY, normalizedMillisInDay);
545:
546:                // We need to have the month, the day, and the day of the week.
547:                // Calling timeToFields will compute the MONTH and DATE fields.
548:                //
549:                // It's tempting to try to use DAY_OF_WEEK here, if it
550:                // is set, but we CAN'T.  Even if it's set, it might have
551:                // been set wrong by the user.  We should rely only on
552:                // the Julian day number, which has been computed correctly
553:                // using the disambiguation algorithm above. [LIU]
554:                int dow = julianDayToDayOfWeek(julianDay);
555:
556:                // It's tempting to try to use DAY_OF_WEEK here, if it
557:                // is set, but we CAN'T.  Even if it's set, it might have
558:                // been set wrong by the user.  We should rely only on
559:                // the Julian day number, which has been computed correctly
560:                // using the disambiguation algorithm above. [LIU]
561:                int dstOffset = getTimeZone().getOffset(AD, this .fields[YEAR],
562:                        this .fields[MONTH], this .fields[DATE], dow,
563:                        normalizedMillisInDay[0])
564:                        - zoneOffset;
565:                // Note: Because we pass in wall millisInDay, rather than
566:                // standard millisInDay, we interpret "1:00 am" on the day
567:                // of cessation of DST as "1:00 am Std" (assuming the time
568:                // of cessation is 2:00 am).
569:
570:                // Store our final computed GMT time, with timezone adjustments.
571:                time = millis - zoneOffset - dstOffset;
572:            }
573:
574:            /**
575:             * Compute the Julian day number under either the Gregorian or the
576:             * Julian calendar, using the given year and the remaining fields.
577:             * @param isGregorian if true, use the Gregorian calendar
578:             * @param year the adjusted year number, with 0 indicating the
579:             * year 1 BC, -1 indicating 2 BC, etc.
580:             * @return the Julian day number
581:             */
582:            private final long calculateJulianDay(boolean isGregorian, int year) {
583:                int month = 0;
584:                long millis = 0;
585:
586:                month = this .fields[MONTH] - JANUARY;
587:
588:                // If the month is out of range, adjust it into range
589:                if (month < 0 || month > 11) {
590:                    int[] rem = new int[1];
591:                    year += floorDivide(month, 12, rem);
592:                    month = rem[0];
593:                }
594:
595:                boolean isLeap = year % 4 == 0;
596:
597:                long julianDay = 365L * (year - 1) + floorDivide((year - 1), 4)
598:                        + (JAN_1_1_JULIAN_DAY - 3);
599:
600:                if (isGregorian) {
601:                    isLeap = isLeap && ((year % 100 != 0) || (year % 400 == 0));
602:                    // Add 2 because Gregorian calendar starts 2 days after Julian calendar
603:                    julianDay += floorDivide((year - 1), 400)
604:                            - floorDivide((year - 1), 100) + 2;
605:                }
606:
607:                // At this point julianDay is the 0-based day BEFORE the first day of
608:                // January 1, year 1 of the given calendar.  If julianDay == 0, it
609:                // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
610:                // or Gregorian).
611:                julianDay += isLeap ? LEAP_NUM_DAYS[month] : NUM_DAYS[month];
612:                julianDay += this .fields[DATE];
613:                return julianDay;
614:            }
615:
616:            /**
617:             * Validates the field values for HOUR_OF_DAY, AM_PM and HOUR
618:             * The calendar will give preference in the following order
619:             * HOUR_OF_DAY, AM_PM, HOUR
620:             */
621:            private void correctTime() {
622:                int value;
623:
624:                if (isSet[HOUR_OF_DAY]) {
625:                    value = this .fields[HOUR_OF_DAY] % 24;
626:                    this .fields[HOUR_OF_DAY] = value;
627:                    this .fields[AM_PM] = (value < 12) ? AM : PM;
628:                    this .isSet[HOUR_OF_DAY] = false;
629:                    return;
630:                }
631:
632:                if (isSet[AM_PM]) {
633:                    // Determines AM PM with the 24 hour clock
634:                    // This prevents the user from inputing an invalid one.
635:                    if (this .fields[AM_PM] != AM && this .fields[AM_PM] != PM) {
636:                        value = this .fields[HOUR_OF_DAY];
637:                        this .fields[AM_PM] = (value < 12) ? AM : PM;
638:                    }
639:                    this .isSet[AM_PM] = false;
640:                }
641:
642:                if (isSet[HOUR]) {
643:                    value = this .fields[HOUR];
644:                    if (value > 12) {
645:                        this .fields[HOUR_OF_DAY] = (value % 12) + 12;
646:                        this .fields[HOUR] = value % 12;
647:                        this .fields[AM_PM] = PM;
648:                    } else {
649:                        if (this .fields[AM_PM] == PM) {
650:                            this .fields[HOUR_OF_DAY] = value + 12;
651:                        } else {
652:                            this .fields[HOUR_OF_DAY] = value;
653:                        }
654:                    }
655:                    this .isSet[HOUR] = false;
656:                }
657:            }
658:
659:            /////////////////
660:            // Implementation
661:            /////////////////
662:
663:            /**
664:             * Converts time as milliseconds to Julian day.
665:             * @param millis the given milliseconds.
666:             * @return the Julian day number.
667:             */
668:            private static final long millisToJulianDay(long millis) {
669:                return EPOCH_JULIAN_DAY + floorDivide(millis, ONE_DAY);
670:            }
671:
672:            /**
673:             * Converts Julian day to time as milliseconds.
674:             * @param julian the given Julian day number.
675:             * @return time as milliseconds.
676:             */
677:            private static final long julianDayToMillis(long julian) {
678:                return (julian - EPOCH_JULIAN_DAY) * ONE_DAY;
679:            }
680:
681:            private static final int julianDayToDayOfWeek(long julian) {
682:                // If julian is negative, then julian%7 will be negative, so we adjust
683:                // accordingly.  We add 1 because Julian day 0 is Monday.
684:                int dayOfWeek = (int) ((julian + 1) % 7);
685:                return dayOfWeek + ((dayOfWeek < 0) ? (7 + SUNDAY) : SUNDAY);
686:            }
687:
688:            /**
689:             * Divide two long integers, returning the floor of the quotient.
690:             * <p>
691:             * Unlike the built-in division, this is mathematically well-behaved.
692:             * E.g., <code>-1/4</code> => 0
693:             * but <code>floorDivide(-1,4)</code> => -1.
694:             * @param numerator the numerator
695:             * @param denominator a divisor which must be > 0
696:             * @return the floor of the quotient.
697:             */
698:            private static final long floorDivide(long numerator,
699:                    long denominator) {
700:                // We do this computation in order to handle
701:                // a numerator of Long.MIN_VALUE correctly
702:                return (numerator >= 0) ? numerator / denominator
703:                        : ((numerator + 1) / denominator) - 1;
704:            }
705:
706:            /**
707:             * Divide two integers, returning the floor of the quotient.
708:             * <p>
709:             * Unlike the built-in division, this is mathematically well-behaved.
710:             * E.g., <code>-1/4</code> => 0
711:             * but <code>floorDivide(-1,4)</code> => -1.
712:             * @param numerator the numerator
713:             * @param denominator a divisor which must be > 0
714:             * @return the floor of the quotient.
715:             */
716:            private static final int floorDivide(int numerator, int denominator) {
717:                // We do this computation in order to handle
718:                // a numerator of Integer.MIN_VALUE correctly
719:                return (numerator >= 0) ? numerator / denominator
720:                        : ((numerator + 1) / denominator) - 1;
721:            }
722:
723:            /**
724:             * Divide two integers, returning the floor of the quotient, and
725:             * the modulus remainder.
726:             * <p>
727:             * Unlike the built-in division, this is mathematically well-behaved.
728:             * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1,
729:             * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3.
730:             * @param numerator the numerator
731:             * @param denominator a divisor which must be > 0
732:             * @param remainder an array of at least one element in which the value
733:             * <code>numerator mod denominator</code> is returned. Unlike <code>numerator
734:             * % denominator</code>, this will always be non-negative.
735:             * @return the floor of the quotient.
736:             */
737:            private static final int floorDivide(int numerator,
738:                    int denominator, int[] remainder) {
739:
740:                if (numerator >= 0) {
741:                    remainder[0] = numerator % denominator;
742:                    return numerator / denominator;
743:                }
744:                int quotient = ((numerator + 1) / denominator) - 1;
745:                remainder[0] = numerator - (quotient * denominator);
746:                return quotient;
747:            }
748:
749:            /**
750:             * Divide two integers, returning the floor of the quotient, and
751:             * the modulus remainder.
752:             * <p>
753:             * Unlike the built-in division, this is mathematically well-behaved.
754:             * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1,
755:             * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3.
756:             * @param numerator the numerator
757:             * @param denominator a divisor which must be > 0
758:             * @param remainder an array of at least one element in which the value
759:             * <code>numerator mod denominator</code> is returned. Unlike <code>numerator
760:             * % denominator</code>, this will always be non-negative.
761:             * @return the floor of the quotient.
762:             */
763:            private static final int floorDivide(long numerator,
764:                    int denominator, int[] remainder) {
765:
766:                if (numerator >= 0) {
767:                    remainder[0] = (int) (numerator % denominator);
768:                    return (int) (numerator / denominator);
769:                }
770:                int quotient = (int) (((numerator + 1) / denominator) - 1);
771:                remainder[0] = (int) (numerator - (quotient * denominator));
772:                return quotient;
773:            }
774:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.