Source Code Cross Referenced for GregorianCalendar.java in  » Apache-Harmony-Java-SE » java-package » java » util » 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 » Apache Harmony Java SE » java package » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package java.util;
0019:
0020:        import java.io.IOException;
0021:        import java.io.ObjectInputStream;
0022:        import java.io.ObjectOutputStream;
0023:
0024:        /**
0025:         * GregorianCalendar provides the conversion between Dates and integer calendar
0026:         * fields, such as the month, year or minute, for the Gregorian calendar. See
0027:         * Calendar for the defined fields.
0028:         * 
0029:         * @see Calendar
0030:         * @see TimeZone
0031:         * @see SimpleTimeZone
0032:         */
0033:        public class GregorianCalendar extends Calendar {
0034:
0035:            private static final long serialVersionUID = -8125100834729963327L;
0036:
0037:            /**
0038:             * Value for the BC era.
0039:             */
0040:            public static final int BC = 0;
0041:
0042:            /**
0043:             * Value for the AD era.
0044:             */
0045:            public static final int AD = 1;
0046:
0047:            private static final long defaultGregorianCutover = -12219292800000l;
0048:
0049:            private long gregorianCutover = defaultGregorianCutover;
0050:
0051:            private transient int changeYear = 1582;
0052:
0053:            private transient int julianSkew = ((changeYear - 2000) / 400)
0054:                    + julianError() - ((changeYear - 2000) / 100);
0055:
0056:            static byte[] DaysInMonth = new byte[] { 31, 28, 31, 30, 31, 30,
0057:                    31, 31, 30, 31, 30, 31 };
0058:
0059:            private static int[] DaysInYear = new int[] { 0, 31, 59, 90, 120,
0060:                    151, 181, 212, 243, 273, 304, 334 };
0061:
0062:            private static int[] maximums = new int[] { 1, 292278994, 11, 53,
0063:                    6, 31, 366, 7, 6, 1, 11, 23, 59, 59, 999, 14 * 3600 * 1000,
0064:                    7200000 };
0065:
0066:            private static int[] minimums = new int[] { 0, 1, 0, 1, 0, 1, 1, 1,
0067:                    1, 0, 0, 0, 0, 0, 0, -13 * 3600 * 1000, 0 };
0068:
0069:            private static int[] leastMaximums = new int[] { 1, 292269054, 11,
0070:                    50, 3, 28, 355, 7, 3, 1, 11, 23, 59, 59, 999, 50400000,
0071:                    1200000 };
0072:
0073:            private boolean isCached;
0074:
0075:            private int cachedFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
0076:
0077:            private long nextMidnightMillis = 0L;
0078:
0079:            private long lastMidnightMillis = 0L;
0080:
0081:            private int currentYearSkew = 10;
0082:
0083:            private int lastYearSkew = 0;
0084:
0085:            /**
0086:             * Constructs a new GregorianCalendar initialized to the current date and
0087:             * time.
0088:             */
0089:            public GregorianCalendar() {
0090:                this (TimeZone.getDefault(), Locale.getDefault());
0091:            }
0092:
0093:            /**
0094:             * Constructs a new GregorianCalendar initialized to midnight in the default
0095:             * time zone on the specified date.
0096:             * 
0097:             * @param year
0098:             *            the year
0099:             * @param month
0100:             *            the month
0101:             * @param day
0102:             *            the day of the month
0103:             */
0104:            public GregorianCalendar(int year, int month, int day) {
0105:                super (TimeZone.getDefault(), Locale.getDefault());
0106:                set(year, month, day);
0107:            }
0108:
0109:            /**
0110:             * Constructs a new GregorianCalendar initialized to the specified date and
0111:             * time.
0112:             * 
0113:             * @param year
0114:             *            the year
0115:             * @param month
0116:             *            the month
0117:             * @param day
0118:             *            the day of the month
0119:             * @param hour
0120:             *            the hour
0121:             * @param minute
0122:             *            the minute
0123:             */
0124:            public GregorianCalendar(int year, int month, int day, int hour,
0125:                    int minute) {
0126:                super (TimeZone.getDefault(), Locale.getDefault());
0127:                set(year, month, day, hour, minute);
0128:            }
0129:
0130:            /**
0131:             * Constructs a new GregorianCalendar initialized to the specified date and
0132:             * time.
0133:             * 
0134:             * @param year
0135:             *            the year
0136:             * @param month
0137:             *            the month
0138:             * @param day
0139:             *            the day of the month
0140:             * @param hour
0141:             *            the hour
0142:             * @param minute
0143:             *            the minute
0144:             * @param second
0145:             *            the second
0146:             */
0147:            public GregorianCalendar(int year, int month, int day, int hour,
0148:                    int minute, int second) {
0149:                super (TimeZone.getDefault(), Locale.getDefault());
0150:                set(year, month, day, hour, minute, second);
0151:            }
0152:
0153:            GregorianCalendar(long milliseconds) {
0154:                this (false);
0155:                setTimeInMillis(milliseconds);
0156:            }
0157:
0158:            /**
0159:             * Constructs a new GregorianCalendar initialized to the current date and
0160:             * time and using the specified Locale.
0161:             * 
0162:             * @param locale
0163:             *            the Locale
0164:             */
0165:            public GregorianCalendar(Locale locale) {
0166:                this (TimeZone.getDefault(), locale);
0167:            }
0168:
0169:            /**
0170:             * Constructs a new GregorianCalendar initialized to the current date and
0171:             * time and using the specified TimeZone.
0172:             * 
0173:             * @param timezone
0174:             *            the TimeZone
0175:             */
0176:            public GregorianCalendar(TimeZone timezone) {
0177:                this (timezone, Locale.getDefault());
0178:            }
0179:
0180:            /**
0181:             * Constructs a new GregorianCalendar initialized to the current date and
0182:             * time and using the specified TimeZone and Locale.
0183:             * 
0184:             * @param timezone
0185:             *            the TimeZone
0186:             * @param locale
0187:             *            the Locale
0188:             */
0189:            public GregorianCalendar(TimeZone timezone, Locale locale) {
0190:                super (timezone, locale);
0191:                setTimeInMillis(System.currentTimeMillis());
0192:            }
0193:
0194:            GregorianCalendar(boolean ignored) {
0195:                super (TimeZone.getDefault());
0196:                setFirstDayOfWeek(SUNDAY);
0197:                setMinimalDaysInFirstWeek(1);
0198:            }
0199:
0200:            /**
0201:             * Adds the specified amount to a Calendar field.
0202:             * 
0203:             * @param field
0204:             *            the Calendar field to modify
0205:             * @param value
0206:             *            the amount to add to the field
0207:             * 
0208:             * @exception IllegalArgumentException
0209:             *                when the specified field is DST_OFFSET or ZONE_OFFSET.
0210:             */
0211:            @Override
0212:            public void add(int field, int value) {
0213:                if (value == 0) {
0214:                    return;
0215:                }
0216:                if (field < 0 || field >= ZONE_OFFSET) {
0217:                    throw new IllegalArgumentException();
0218:                }
0219:
0220:                isCached = false;
0221:
0222:                if (field == ERA) {
0223:                    complete();
0224:                    if (fields[ERA] == AD) {
0225:                        if (value >= 0) {
0226:                            return;
0227:                        }
0228:                        set(ERA, BC);
0229:                    } else {
0230:                        if (value <= 0) {
0231:                            return;
0232:                        }
0233:                        set(ERA, AD);
0234:                    }
0235:                    complete();
0236:                    return;
0237:                }
0238:
0239:                if (field == YEAR || field == MONTH) {
0240:                    complete();
0241:                    if (field == MONTH) {
0242:                        int month = fields[MONTH] + value;
0243:                        if (month < 0) {
0244:                            value = (month - 11) / 12;
0245:                            month = 12 + (month % 12);
0246:                        } else {
0247:                            value = month / 12;
0248:                        }
0249:                        set(MONTH, month % 12);
0250:                    }
0251:                    set(YEAR, fields[YEAR] + value);
0252:                    int days = daysInMonth(isLeapYear(fields[YEAR]),
0253:                            fields[MONTH]);
0254:                    if (fields[DATE] > days) {
0255:                        set(DATE, days);
0256:                    }
0257:                    complete();
0258:                    return;
0259:                }
0260:
0261:                long multiplier = 0;
0262:                getTimeInMillis(); // Update the time
0263:                switch (field) {
0264:                case MILLISECOND:
0265:                    time += value;
0266:                    break;
0267:                case SECOND:
0268:                    time += value * 1000L;
0269:                    break;
0270:                case MINUTE:
0271:                    time += value * 60000L;
0272:                    break;
0273:                case HOUR:
0274:                case HOUR_OF_DAY:
0275:                    time += value * 3600000L;
0276:                    break;
0277:                case AM_PM:
0278:                    multiplier = 43200000L;
0279:                    break;
0280:                case DATE:
0281:                case DAY_OF_YEAR:
0282:                case DAY_OF_WEEK:
0283:                    multiplier = 86400000L;
0284:                    break;
0285:                case WEEK_OF_YEAR:
0286:                case WEEK_OF_MONTH:
0287:                case DAY_OF_WEEK_IN_MONTH:
0288:                    multiplier = 604800000L;
0289:                    break;
0290:                }
0291:                if (multiplier > 0) {
0292:                    int zoneOffset = getTimeZone().getRawOffset();
0293:                    int offset = getOffset(time + zoneOffset);
0294:                    time += value * multiplier;
0295:                    int newOffset = getOffset(time + zoneOffset);
0296:                    // Adjust for moving over a DST boundary
0297:                    if (newOffset != offset) {
0298:                        time += offset - newOffset;
0299:                    }
0300:                }
0301:                areFieldsSet = false;
0302:                complete();
0303:            }
0304:
0305:            /**
0306:             * Creates new instance of GregorianCalendar with the same properties.
0307:             * 
0308:             * @return a shallow copy of this GregorianCalendar
0309:             */
0310:            @Override
0311:            public Object clone() {
0312:                GregorianCalendar this Clone = (GregorianCalendar) super .clone();
0313:                this Clone.cachedFields = cachedFields.clone();
0314:                return this Clone;
0315:            }
0316:
0317:            private final void fullFieldsCalc(long timeVal, int millis,
0318:                    int zoneOffset) {
0319:                long days = timeVal / 86400000;
0320:
0321:                if (millis < 0) {
0322:                    millis += 86400000;
0323:                    days--;
0324:                }
0325:                // Cannot add ZONE_OFFSET to time as it might overflow
0326:                millis += zoneOffset;
0327:                while (millis < 0) {
0328:                    millis += 86400000;
0329:                    days--;
0330:                }
0331:                while (millis >= 86400000) {
0332:                    millis -= 86400000;
0333:                    days++;
0334:                }
0335:
0336:                int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
0337:                fields[DAY_OF_YEAR] = dayOfYear;
0338:                if (fields[YEAR] == changeYear
0339:                        && gregorianCutover <= timeVal + zoneOffset) {
0340:                    dayOfYear += currentYearSkew;
0341:                }
0342:                int month = dayOfYear / 32;
0343:                boolean leapYear = isLeapYear(fields[YEAR]);
0344:                int date = dayOfYear - daysInYear(leapYear, month);
0345:                if (date > daysInMonth(leapYear, month)) {
0346:                    date -= daysInMonth(leapYear, month);
0347:                    month++;
0348:                }
0349:                fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
0350:                int dstOffset = fields[YEAR] <= 0 ? 0 : getTimeZone()
0351:                        .getOffset(AD, fields[YEAR], month, date,
0352:                                fields[DAY_OF_WEEK], millis);
0353:                if (fields[YEAR] > 0) {
0354:                    dstOffset -= zoneOffset;
0355:                }
0356:                fields[DST_OFFSET] = dstOffset;
0357:                if (dstOffset != 0) {
0358:                    long oldDays = days;
0359:                    millis += dstOffset;
0360:                    if (millis < 0) {
0361:                        millis += 86400000;
0362:                        days--;
0363:                    } else if (millis >= 86400000) {
0364:                        millis -= 86400000;
0365:                        days++;
0366:                    }
0367:                    if (oldDays != days) {
0368:                        dayOfYear = computeYearAndDay(days, timeVal
0369:                                - zoneOffset + dstOffset);
0370:                        fields[DAY_OF_YEAR] = dayOfYear;
0371:                        if (fields[YEAR] == changeYear
0372:                                && gregorianCutover <= timeVal - zoneOffset
0373:                                        + dstOffset) {
0374:                            dayOfYear += currentYearSkew;
0375:                        }
0376:                        month = dayOfYear / 32;
0377:                        leapYear = isLeapYear(fields[YEAR]);
0378:                        date = dayOfYear - daysInYear(leapYear, month);
0379:                        if (date > daysInMonth(leapYear, month)) {
0380:                            date -= daysInMonth(leapYear, month);
0381:                            month++;
0382:                        }
0383:                        fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
0384:                    }
0385:                }
0386:
0387:                fields[MILLISECOND] = (millis % 1000);
0388:                millis /= 1000;
0389:                fields[SECOND] = (millis % 60);
0390:                millis /= 60;
0391:                fields[MINUTE] = (millis % 60);
0392:                millis /= 60;
0393:                fields[HOUR_OF_DAY] = (millis % 24);
0394:                millis /= 24;
0395:                fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
0396:                fields[HOUR] = fields[HOUR_OF_DAY] % 12;
0397:
0398:                if (fields[YEAR] <= 0) {
0399:                    fields[ERA] = BC;
0400:                    fields[YEAR] = -fields[YEAR] + 1;
0401:                } else {
0402:                    fields[ERA] = AD;
0403:                }
0404:                fields[MONTH] = month;
0405:                fields[DATE] = date;
0406:                fields[DAY_OF_WEEK_IN_MONTH] = (date - 1) / 7 + 1;
0407:                fields[WEEK_OF_MONTH] = (date - 1 + mod7(days - date - 2
0408:                        - (getFirstDayOfWeek() - 1))) / 7 + 1;
0409:                int daysFromStart = mod7(days - 3 - (fields[DAY_OF_YEAR] - 1)
0410:                        - (getFirstDayOfWeek() - 1));
0411:                int week = (fields[DAY_OF_YEAR] - 1 + daysFromStart)
0412:                        / 7
0413:                        + (7 - daysFromStart >= getMinimalDaysInFirstWeek() ? 1
0414:                                : 0);
0415:                if (week == 0) {
0416:                    fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart
0417:                            - (isLeapYear(fields[YEAR] - 1) ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 53
0418:                            : 52;
0419:                } else if (fields[DAY_OF_YEAR] >= (leapYear ? 367 : 366)
0420:                        - mod7(daysFromStart + (leapYear ? 2 : 1))) {
0421:                    fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart
0422:                            + (leapYear ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 1
0423:                            : week;
0424:                } else {
0425:                    fields[WEEK_OF_YEAR] = week;
0426:                }
0427:            }
0428:
0429:            private final void cachedFieldsCheckAndGet(long timeVal,
0430:                    long newTimeMillis, long newTimeMillisAdjusted, int millis,
0431:                    int zoneOffset) {
0432:                int dstOffset = fields[DST_OFFSET];
0433:                if (!isCached
0434:                        || newTimeMillis >= nextMidnightMillis
0435:                        || newTimeMillis <= lastMidnightMillis
0436:                        || cachedFields[4] != zoneOffset
0437:                        || (dstOffset == 0 && (newTimeMillisAdjusted >= nextMidnightMillis))
0438:                        || (dstOffset != 0 && (newTimeMillisAdjusted <= lastMidnightMillis))) {
0439:                    fullFieldsCalc(timeVal, millis, zoneOffset);
0440:                    isCached = false;
0441:                } else {
0442:                    fields[YEAR] = cachedFields[0];
0443:                    fields[MONTH] = cachedFields[1];
0444:                    fields[DATE] = cachedFields[2];
0445:                    fields[DAY_OF_WEEK] = cachedFields[3];
0446:                    fields[ERA] = cachedFields[5];
0447:                    fields[WEEK_OF_YEAR] = cachedFields[6];
0448:                    fields[WEEK_OF_MONTH] = cachedFields[7];
0449:                    fields[DAY_OF_YEAR] = cachedFields[8];
0450:                    fields[DAY_OF_WEEK_IN_MONTH] = cachedFields[9];
0451:                }
0452:            }
0453:
0454:            /**
0455:             * Computes the Calendar fields from the time.
0456:             */
0457:            @Override
0458:            protected void computeFields() {
0459:                int zoneOffset = getTimeZone().getRawOffset();
0460:
0461:                fields[ZONE_OFFSET] = zoneOffset;
0462:
0463:                int millis = (int) (time % 86400000);
0464:                int savedMillis = millis;
0465:                int dstOffset = fields[DST_OFFSET];
0466:                // compute without a change in daylight saving time
0467:                int offset = zoneOffset + dstOffset;
0468:                long newTime = time + offset;
0469:
0470:                if (time > 0L && newTime < 0L && offset > 0) {
0471:                    newTime = 0x7fffffffffffffffL;
0472:                } else if (time < 0L && newTime > 0L && offset < 0) {
0473:                    newTime = 0x8000000000000000L;
0474:                }
0475:
0476:                if (isCached) {
0477:                    if (millis < 0) {
0478:                        millis += 86400000;
0479:                    }
0480:
0481:                    // Cannot add ZONE_OFFSET to time as it might overflow
0482:                    millis += zoneOffset;
0483:                    millis += dstOffset;
0484:
0485:                    if (millis < 0) {
0486:                        millis += 86400000;
0487:                    } else if (millis >= 86400000) {
0488:                        millis -= 86400000;
0489:                    }
0490:
0491:                    fields[MILLISECOND] = (millis % 1000);
0492:                    millis /= 1000;
0493:                    fields[SECOND] = (millis % 60);
0494:                    millis /= 60;
0495:                    fields[MINUTE] = (millis % 60);
0496:                    millis /= 60;
0497:                    fields[HOUR_OF_DAY] = (millis % 24);
0498:                    millis /= 24;
0499:                    fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
0500:                    fields[HOUR] = fields[HOUR_OF_DAY] % 12;
0501:
0502:                    long newTimeAdjusted = newTime;
0503:                    if (getTimeZone().useDaylightTime()) {
0504:                        int dstSavings = ((SimpleTimeZone) getTimeZone())
0505:                                .getDSTSavings();
0506:                        newTimeAdjusted += (dstOffset == 0) ? dstSavings
0507:                                : -dstSavings;
0508:                    }
0509:
0510:                    if (newTime > 0L && newTimeAdjusted < 0L && dstOffset == 0) {
0511:                        newTimeAdjusted = 0x7fffffffffffffffL;
0512:                    } else if (newTime < 0L && newTimeAdjusted > 0L
0513:                            && dstOffset != 0) {
0514:                        newTimeAdjusted = 0x8000000000000000L;
0515:                    }
0516:
0517:                    cachedFieldsCheckAndGet(time, newTime, newTimeAdjusted,
0518:                            savedMillis, zoneOffset);
0519:                } else {
0520:                    fullFieldsCalc(time, savedMillis, zoneOffset);
0521:                }
0522:
0523:                for (int i = 0; i < FIELD_COUNT; i++) {
0524:                    isSet[i] = true;
0525:                }
0526:
0527:                // Caching
0528:                if (!isCached
0529:                        && newTime != 0x7fffffffffffffffL
0530:                        && newTime != 0x8000000000000000L
0531:                        && (!getTimeZone().useDaylightTime() || getTimeZone() instanceof  SimpleTimeZone)) {
0532:                    int cacheMillis = 0;
0533:
0534:                    cachedFields[0] = fields[YEAR];
0535:                    cachedFields[1] = fields[MONTH];
0536:                    cachedFields[2] = fields[DATE];
0537:                    cachedFields[3] = fields[DAY_OF_WEEK];
0538:                    cachedFields[4] = zoneOffset;
0539:                    cachedFields[5] = fields[ERA];
0540:                    cachedFields[6] = fields[WEEK_OF_YEAR];
0541:                    cachedFields[7] = fields[WEEK_OF_MONTH];
0542:                    cachedFields[8] = fields[DAY_OF_YEAR];
0543:                    cachedFields[9] = fields[DAY_OF_WEEK_IN_MONTH];
0544:
0545:                    cacheMillis += (23 - fields[HOUR_OF_DAY]) * 60 * 60 * 1000;
0546:                    cacheMillis += (59 - fields[MINUTE]) * 60 * 1000;
0547:                    cacheMillis += (59 - fields[SECOND]) * 1000;
0548:                    nextMidnightMillis = newTime + cacheMillis;
0549:
0550:                    cacheMillis = fields[HOUR_OF_DAY] * 60 * 60 * 1000;
0551:                    cacheMillis += fields[MINUTE] * 60 * 1000;
0552:                    cacheMillis += fields[SECOND] * 1000;
0553:                    lastMidnightMillis = newTime - cacheMillis;
0554:
0555:                    isCached = true;
0556:                }
0557:            }
0558:
0559:            /**
0560:             * Computes the time from the Calendar fields.
0561:             * 
0562:             * @exception IllegalArgumentException
0563:             *                when the time cannot be computed from the current field
0564:             *                values
0565:             */
0566:            @Override
0567:            protected void computeTime() {
0568:                if (!isLenient()) {
0569:                    if (isSet[HOUR_OF_DAY]) {
0570:                        if (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23) {
0571:                            throw new IllegalArgumentException();
0572:                        }
0573:                    } else if (isSet[HOUR]
0574:                            && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
0575:                        throw new IllegalArgumentException();
0576:                    }
0577:                    if (isSet[MINUTE]
0578:                            && (fields[MINUTE] < 0 || fields[MINUTE] > 59)) {
0579:                        throw new IllegalArgumentException();
0580:                    }
0581:                    if (isSet[SECOND]
0582:                            && (fields[SECOND] < 0 || fields[SECOND] > 59)) {
0583:                        throw new IllegalArgumentException();
0584:                    }
0585:                    if (isSet[MILLISECOND]
0586:                            && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999)) {
0587:                        throw new IllegalArgumentException();
0588:                    }
0589:                    if (isSet[WEEK_OF_YEAR]
0590:                            && (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > 53)) {
0591:                        throw new IllegalArgumentException();
0592:                    }
0593:                    if (isSet[DAY_OF_WEEK]
0594:                            && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7)) {
0595:                        throw new IllegalArgumentException();
0596:                    }
0597:                    if (isSet[DAY_OF_WEEK_IN_MONTH]
0598:                            && (fields[DAY_OF_WEEK_IN_MONTH] < 1 || fields[DAY_OF_WEEK_IN_MONTH] > 6)) {
0599:                        throw new IllegalArgumentException();
0600:                    }
0601:                    if (isSet[WEEK_OF_MONTH]
0602:                            && (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > 6)) {
0603:                        throw new IllegalArgumentException();
0604:                    }
0605:                    if (isSet[AM_PM] && fields[AM_PM] != AM
0606:                            && fields[AM_PM] != PM) {
0607:                        throw new IllegalArgumentException();
0608:                    }
0609:                    if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
0610:                        throw new IllegalArgumentException();
0611:                    }
0612:                    if (isSet[YEAR]) {
0613:                        if (isSet[ERA]
0614:                                && fields[ERA] == BC
0615:                                && (fields[YEAR] < 1 || fields[YEAR] > 292269054)) {
0616:                            throw new IllegalArgumentException();
0617:                        } else if (fields[YEAR] < 1 || fields[YEAR] > 292278994) {
0618:                            throw new IllegalArgumentException();
0619:                        }
0620:                    }
0621:                    if (isSet[MONTH]
0622:                            && (fields[MONTH] < 0 || fields[MONTH] > 11)) {
0623:                        throw new IllegalArgumentException();
0624:                    }
0625:                }
0626:
0627:                long timeVal;
0628:                long hour = 0;
0629:                if (isSet[HOUR_OF_DAY] && lastTimeFieldSet != HOUR) {
0630:                    hour = fields[HOUR_OF_DAY];
0631:                } else if (isSet[HOUR]) {
0632:                    hour = (fields[AM_PM] * 12) + fields[HOUR];
0633:                }
0634:                timeVal = hour * 3600000;
0635:
0636:                if (isSet[MINUTE]) {
0637:                    timeVal += ((long) fields[MINUTE]) * 60000;
0638:                }
0639:                if (isSet[SECOND]) {
0640:                    timeVal += ((long) fields[SECOND]) * 1000;
0641:                }
0642:                if (isSet[MILLISECOND]) {
0643:                    timeVal += fields[MILLISECOND];
0644:                }
0645:
0646:                long days;
0647:                int year = isSet[YEAR] ? fields[YEAR] : 1970;
0648:                if (isSet[ERA]) {
0649:                    // Always test for valid ERA, even if the Calendar is lenient
0650:                    if (fields[ERA] != BC && fields[ERA] != AD) {
0651:                        throw new IllegalArgumentException();
0652:                    }
0653:                    if (fields[ERA] == BC) {
0654:                        year = 1 - year;
0655:                    }
0656:                }
0657:
0658:                boolean weekMonthSet = isSet[WEEK_OF_MONTH]
0659:                        || isSet[DAY_OF_WEEK_IN_MONTH];
0660:                boolean useMonth = (isSet[DATE] || isSet[MONTH] || weekMonthSet)
0661:                        && lastDateFieldSet != DAY_OF_YEAR;
0662:                if (useMonth
0663:                        && (lastDateFieldSet == DAY_OF_WEEK || lastDateFieldSet == WEEK_OF_YEAR)) {
0664:                    if (isSet[WEEK_OF_YEAR] && isSet[DAY_OF_WEEK]) {
0665:                        useMonth = lastDateFieldSet != WEEK_OF_YEAR
0666:                                && weekMonthSet && isSet[DAY_OF_WEEK];
0667:                    } else if (isSet[DAY_OF_YEAR]) {
0668:                        useMonth = isSet[DATE] && isSet[MONTH];
0669:                    }
0670:                }
0671:
0672:                if (useMonth) {
0673:                    int month = fields[MONTH];
0674:                    year += month / 12;
0675:                    month %= 12;
0676:                    if (month < 0) {
0677:                        year--;
0678:                        month += 12;
0679:                    }
0680:                    boolean leapYear = isLeapYear(year);
0681:                    days = daysFromBaseYear(year) + daysInYear(leapYear, month);
0682:                    boolean useDate = isSet[DATE];
0683:                    if (useDate
0684:                            && (lastDateFieldSet == DAY_OF_WEEK
0685:                                    || lastDateFieldSet == WEEK_OF_MONTH || lastDateFieldSet == DAY_OF_WEEK_IN_MONTH)) {
0686:                        useDate = !(isSet[DAY_OF_WEEK] && weekMonthSet);
0687:                    }
0688:                    if (useDate) {
0689:                        if (!isLenient()
0690:                                && (fields[DATE] < 1 || fields[DATE] > daysInMonth(
0691:                                        leapYear, month))) {
0692:                            throw new IllegalArgumentException();
0693:                        }
0694:                        days += fields[DATE] - 1;
0695:                    } else {
0696:                        int dayOfWeek;
0697:                        if (isSet[DAY_OF_WEEK]) {
0698:                            dayOfWeek = fields[DAY_OF_WEEK] - 1;
0699:                        } else {
0700:                            dayOfWeek = getFirstDayOfWeek() - 1;
0701:                        }
0702:                        if (isSet[WEEK_OF_MONTH]
0703:                                && lastDateFieldSet != DAY_OF_WEEK_IN_MONTH) {
0704:                            int skew = mod7(days - 3
0705:                                    - (getFirstDayOfWeek() - 1));
0706:                            days += (fields[WEEK_OF_MONTH] - 1) * 7
0707:                                    + mod7(skew + dayOfWeek - (days - 3))
0708:                                    - skew;
0709:                        } else if (isSet[DAY_OF_WEEK_IN_MONTH]) {
0710:                            if (fields[DAY_OF_WEEK_IN_MONTH] >= 0) {
0711:                                days += mod7(dayOfWeek - (days - 3))
0712:                                        + (fields[DAY_OF_WEEK_IN_MONTH] - 1)
0713:                                        * 7;
0714:                            } else {
0715:                                days += daysInMonth(leapYear, month)
0716:                                        + mod7(dayOfWeek
0717:                                                - (days
0718:                                                        + daysInMonth(leapYear,
0719:                                                                month) - 3))
0720:                                        + fields[DAY_OF_WEEK_IN_MONTH] * 7;
0721:                            }
0722:                        } else if (isSet[DAY_OF_WEEK]) {
0723:                            int skew = mod7(days - 3
0724:                                    - (getFirstDayOfWeek() - 1));
0725:                            days += mod7(mod7(skew + dayOfWeek - (days - 3))
0726:                                    - skew);
0727:                        }
0728:                    }
0729:                } else {
0730:                    boolean useWeekYear = isSet[WEEK_OF_YEAR]
0731:                            && lastDateFieldSet != DAY_OF_YEAR;
0732:                    if (useWeekYear && isSet[DAY_OF_YEAR]) {
0733:                        useWeekYear = isSet[DAY_OF_WEEK];
0734:                    }
0735:                    days = daysFromBaseYear(year);
0736:                    if (useWeekYear) {
0737:                        int dayOfWeek;
0738:                        if (isSet[DAY_OF_WEEK]) {
0739:                            dayOfWeek = fields[DAY_OF_WEEK] - 1;
0740:                        } else {
0741:                            dayOfWeek = getFirstDayOfWeek() - 1;
0742:                        }
0743:                        int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
0744:                        days += (fields[WEEK_OF_YEAR] - 1) * 7
0745:                                + mod7(skew + dayOfWeek - (days - 3)) - skew;
0746:                        if (7 - skew < getMinimalDaysInFirstWeek()) {
0747:                            days += 7;
0748:                        }
0749:                    } else if (isSet[DAY_OF_YEAR]) {
0750:                        if (!isLenient()
0751:                                && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > (365 + (isLeapYear(year) ? 1
0752:                                        : 0)))) {
0753:                            throw new IllegalArgumentException();
0754:                        }
0755:                        days += fields[DAY_OF_YEAR] - 1;
0756:                    } else if (isSet[DAY_OF_WEEK]) {
0757:                        days += mod7(fields[DAY_OF_WEEK] - 1 - (days - 3));
0758:                    }
0759:                }
0760:                lastDateFieldSet = 0;
0761:
0762:                timeVal += days * 86400000;
0763:                // Use local time to compare with the gregorian change
0764:                if (year == changeYear
0765:                        && timeVal >= gregorianCutover + julianError()
0766:                                * 86400000L) {
0767:                    timeVal -= julianError() * 86400000L;
0768:                }
0769:
0770:                // It is not possible to simply subtract getOffset(timeVal) from timeVal
0771:                // to get UTC.
0772:                // The trick is needed for the moment when DST transition occurs,
0773:                // say 1:00 is a transition time when DST offset becomes +1 hour,
0774:                // then wall time in the interval 1:00 - 2:00 is invalid and is
0775:                // treated as UTC time.
0776:                long timeValWithoutDST = timeVal - getOffset(timeVal)
0777:                        + getTimeZone().getRawOffset();
0778:                timeVal -= getOffset(timeValWithoutDST);
0779:                // Need to update wall time in fields, since it was invalid due to DST
0780:                // transition
0781:                this .time = timeVal;
0782:                if (timeValWithoutDST != timeVal) {
0783:                    computeFields();
0784:                    areFieldsSet = true;
0785:                }
0786:            }
0787:
0788:            private int computeYearAndDay(long dayCount, long localTime) {
0789:                int year = 1970;
0790:                long days = dayCount;
0791:                if (localTime < gregorianCutover) {
0792:                    days -= julianSkew;
0793:                }
0794:                int approxYears;
0795:
0796:                while ((approxYears = (int) (days / 365)) != 0) {
0797:                    year = year + approxYears;
0798:                    days = dayCount - daysFromBaseYear(year);
0799:                }
0800:                if (days < 0) {
0801:                    year = year - 1;
0802:                    days = days + daysInYear(year);
0803:                }
0804:                fields[YEAR] = year;
0805:                return (int) days + 1;
0806:            }
0807:
0808:            private long daysFromBaseYear(int iyear) {
0809:                long year = iyear;
0810:
0811:                if (year >= 1970) {
0812:                    long days = (year - 1970) * 365 + ((year - 1969) / 4);
0813:                    if (year > changeYear) {
0814:                        days -= ((year - 1901) / 100) - ((year - 1601) / 400);
0815:                    } else {
0816:                        if (year == changeYear) {
0817:                            days += currentYearSkew;
0818:                        } else if (year == changeYear - 1) {
0819:                            days += lastYearSkew;
0820:                        } else {
0821:                            days += julianSkew;
0822:                        }
0823:                    }
0824:                    return days;
0825:                } else if (year <= changeYear) {
0826:                    return (year - 1970) * 365 + ((year - 1972) / 4)
0827:                            + julianSkew;
0828:                }
0829:                return (year - 1970) * 365 + ((year - 1972) / 4)
0830:                        - ((year - 2000) / 100) + ((year - 2000) / 400);
0831:            }
0832:
0833:            private int daysInMonth() {
0834:                return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
0835:            }
0836:
0837:            private int daysInMonth(boolean leapYear, int month) {
0838:                if (leapYear && month == FEBRUARY) {
0839:                    return DaysInMonth[month] + 1;
0840:                }
0841:
0842:                return DaysInMonth[month];
0843:            }
0844:
0845:            private int daysInYear(int year) {
0846:                int daysInYear = isLeapYear(year) ? 366 : 365;
0847:                if (year == changeYear) {
0848:                    daysInYear -= currentYearSkew;
0849:                }
0850:                if (year == changeYear - 1) {
0851:                    daysInYear -= lastYearSkew;
0852:                }
0853:                return daysInYear;
0854:            }
0855:
0856:            private int daysInYear(boolean leapYear, int month) {
0857:                if (leapYear && month > FEBRUARY) {
0858:                    return DaysInYear[month] + 1;
0859:                }
0860:
0861:                return DaysInYear[month];
0862:            }
0863:
0864:            /**
0865:             * Compares the specified object to this GregorianCalendar and answer if
0866:             * they are equal. The object must be an instance of GregorianCalendar and
0867:             * have the same properties.
0868:             * 
0869:             * @param object
0870:             *            the object to compare with this object
0871:             * @return true if the specified object is equal to this GregorianCalendar,
0872:             *         false otherwise
0873:             * 
0874:             * @exception IllegalArgumentException
0875:             *                when the time is not set and the time cannot be computed
0876:             *                from the current field values
0877:             * 
0878:             * @see #hashCode
0879:             */
0880:            @Override
0881:            public boolean equals(Object object) {
0882:                return super .equals(object)
0883:                        && gregorianCutover == ((GregorianCalendar) object).gregorianCutover;
0884:            }
0885:
0886:            /**
0887:             * Gets the maximum value of the specified field for the current date. For
0888:             * example, the maximum number of days in the current month.
0889:             * 
0890:             * @param field
0891:             *            the field
0892:             * @return the maximum value of the specified field
0893:             */
0894:            @Override
0895:            public int getActualMaximum(int field) {
0896:                int value;
0897:                if ((value = maximums[field]) == leastMaximums[field]) {
0898:                    return value;
0899:                }
0900:
0901:                switch (field) {
0902:                case WEEK_OF_YEAR:
0903:                case WEEK_OF_MONTH:
0904:                    isCached = false;
0905:                    break;
0906:                }
0907:
0908:                complete();
0909:                long orgTime = time;
0910:                int result = 0;
0911:                switch (field) {
0912:                case WEEK_OF_YEAR:
0913:                    set(DATE, 31);
0914:                    set(MONTH, DECEMBER);
0915:                    result = get(WEEK_OF_YEAR);
0916:                    if (result == 1) {
0917:                        set(DATE, 31 - 7);
0918:                        result = get(WEEK_OF_YEAR);
0919:                    }
0920:                    areFieldsSet = false;
0921:                    break;
0922:                case WEEK_OF_MONTH:
0923:                    set(DATE, daysInMonth());
0924:                    result = get(WEEK_OF_MONTH);
0925:                    areFieldsSet = false;
0926:                    break;
0927:                case DATE:
0928:                    return daysInMonth();
0929:                case DAY_OF_YEAR:
0930:                    return daysInYear(fields[YEAR]);
0931:                case DAY_OF_WEEK_IN_MONTH:
0932:                    result = get(DAY_OF_WEEK_IN_MONTH)
0933:                            + ((daysInMonth() - get(DATE)) / 7);
0934:                    break;
0935:                case YEAR:
0936:                    GregorianCalendar clone = (GregorianCalendar) clone();
0937:                    if (get(ERA) == AD) {
0938:                        clone.setTimeInMillis(Long.MAX_VALUE);
0939:                    } else {
0940:                        clone.setTimeInMillis(Long.MIN_VALUE);
0941:                    }
0942:                    result = clone.get(YEAR);
0943:                    clone.set(YEAR, get(YEAR));
0944:                    if (clone.before(this )) {
0945:                        result--;
0946:                    }
0947:                    break;
0948:                case DST_OFFSET:
0949:                    result = getMaximum(DST_OFFSET);
0950:                    break;
0951:                }
0952:                time = orgTime;
0953:                return result;
0954:            }
0955:
0956:            /**
0957:             * Gets the minimum value of the specified field for the current date. For
0958:             * the gregorian calendar, this value is the same as
0959:             * <code>getMinimum()</code>.
0960:             * 
0961:             * @param field
0962:             *            the field
0963:             * @return the minimum value of the specified field
0964:             */
0965:            @Override
0966:            public int getActualMinimum(int field) {
0967:                return getMinimum(field);
0968:            }
0969:
0970:            /**
0971:             * Gets the greatest minimum value of the specified field. For the gregorian
0972:             * calendar, this value is the same as <code>getMinimum()</code>.
0973:             * 
0974:             * @param field
0975:             *            the field
0976:             * @return the greatest minimum value of the specified field
0977:             */
0978:            @Override
0979:            public int getGreatestMinimum(int field) {
0980:                return minimums[field];
0981:            }
0982:
0983:            /**
0984:             * Answers the gregorian change date of this calendar. This is the date on
0985:             * which the gregorian calendar came into effect.
0986:             * 
0987:             * @return a Date which represents the gregorian change date
0988:             */
0989:            public final Date getGregorianChange() {
0990:                return new Date(gregorianCutover);
0991:            }
0992:
0993:            /**
0994:             * Gets the smallest maximum value of the specified field. For example, 28
0995:             * for the day of month field.
0996:             * 
0997:             * @param field
0998:             *            the field
0999:             * @return the smallest maximum value of the specified field
1000:             */
1001:            @Override
1002:            public int getLeastMaximum(int field) {
1003:                // return value for WEEK_OF_YEAR should make corresponding changes when
1004:                // the gregorian change date have been reset.
1005:                if (gregorianCutover != defaultGregorianCutover
1006:                        && field == WEEK_OF_YEAR) {
1007:                    long currentTimeInMillis = time;
1008:                    setTimeInMillis(gregorianCutover);
1009:                    int actual = getActualMaximum(field);
1010:                    setTimeInMillis(currentTimeInMillis);
1011:                    return actual;
1012:                }
1013:                return leastMaximums[field];
1014:            }
1015:
1016:            /**
1017:             * Gets the greatest maximum value of the specified field. For example, 31
1018:             * for the day of month field.
1019:             * 
1020:             * @param field
1021:             *            the field
1022:             * @return the greatest maximum value of the specified field
1023:             */
1024:            @Override
1025:            public int getMaximum(int field) {
1026:                return maximums[field];
1027:            }
1028:
1029:            /**
1030:             * Gets the smallest minimum value of the specified field.
1031:             * 
1032:             * @param field
1033:             *            the field
1034:             * @return the smallest minimum value of the specified field
1035:             */
1036:            @Override
1037:            public int getMinimum(int field) {
1038:                return minimums[field];
1039:            }
1040:
1041:            int getOffset(long localTime) {
1042:                TimeZone timeZone = getTimeZone();
1043:                if (!timeZone.useDaylightTime()) {
1044:                    return timeZone.getRawOffset();
1045:                }
1046:
1047:                long dayCount = localTime / 86400000;
1048:                int millis = (int) (localTime % 86400000);
1049:                if (millis < 0) {
1050:                    millis += 86400000;
1051:                    dayCount--;
1052:                }
1053:
1054:                int year = 1970;
1055:                long days = dayCount;
1056:                if (localTime < gregorianCutover) {
1057:                    days -= julianSkew;
1058:                }
1059:                int approxYears;
1060:
1061:                while ((approxYears = (int) (days / 365)) != 0) {
1062:                    year = year + approxYears;
1063:                    days = dayCount - daysFromBaseYear(year);
1064:                }
1065:                if (days < 0) {
1066:                    year = year - 1;
1067:                    days = days + 365 + (isLeapYear(year) ? 1 : 0);
1068:                    if (year == changeYear && localTime < gregorianCutover) {
1069:                        days -= julianError();
1070:                    }
1071:                }
1072:                if (year <= 0) {
1073:                    return timeZone.getRawOffset();
1074:                }
1075:                int dayOfYear = (int) days + 1;
1076:
1077:                int month = dayOfYear / 32;
1078:                boolean leapYear = isLeapYear(year);
1079:                int date = dayOfYear - daysInYear(leapYear, month);
1080:                if (date > daysInMonth(leapYear, month)) {
1081:                    date -= daysInMonth(leapYear, month);
1082:                    month++;
1083:                }
1084:                int dayOfWeek = mod7(dayCount - 3) + 1;
1085:                int offset = timeZone.getOffset(AD, year, month, date,
1086:                        dayOfWeek, millis);
1087:                return offset;
1088:            }
1089:
1090:            /**
1091:             * Answers an integer hash code for the receiver. Objects which are equal
1092:             * answer the same value for this method.
1093:             * 
1094:             * @return the receiver's hash
1095:             * 
1096:             * @see #equals
1097:             */
1098:            @Override
1099:            public int hashCode() {
1100:                return super .hashCode()
1101:                        + ((int) (gregorianCutover >>> 32) ^ (int) gregorianCutover);
1102:            }
1103:
1104:            /**
1105:             * Answers if the specified year is a leap year.
1106:             * 
1107:             * @param year
1108:             *            the year
1109:             * @return true if the specified year is a leap year, false otherwise
1110:             */
1111:            public boolean isLeapYear(int year) {
1112:                if (year > changeYear) {
1113:                    return year % 4 == 0
1114:                            && (year % 100 != 0 || year % 400 == 0);
1115:                }
1116:
1117:                return year % 4 == 0;
1118:            }
1119:
1120:            private int julianError() {
1121:                return changeYear / 100 - changeYear / 400 - 2;
1122:            }
1123:
1124:            private int mod(int value, int mod) {
1125:                int rem = value % mod;
1126:                if (value < 0 && rem < 0) {
1127:                    return rem + mod;
1128:                }
1129:                return rem;
1130:            }
1131:
1132:            private int mod7(long num1) {
1133:                int rem = (int) (num1 % 7);
1134:                if (num1 < 0 && rem < 0) {
1135:                    return rem + 7;
1136:                }
1137:                return rem;
1138:            }
1139:
1140:            /**
1141:             * Adds the specified amount the specified field and wrap the value of the
1142:             * field when it goes beyond the maximum or minimum value for the current
1143:             * date. Other fields will be adjusted as required to maintain a consistent
1144:             * date.
1145:             * 
1146:             * @param field
1147:             *            the field to roll
1148:             * @param value
1149:             *            the amount to add
1150:             * 
1151:             * @exception IllegalArgumentException
1152:             *                when an invalid field is specified
1153:             */
1154:            @Override
1155:            public void roll(int field, int value) {
1156:                if (value == 0) {
1157:                    return;
1158:                }
1159:                if (field < 0 || field >= ZONE_OFFSET) {
1160:                    throw new IllegalArgumentException();
1161:                }
1162:
1163:                isCached = false;
1164:
1165:                complete();
1166:                int days, day, mod, maxWeeks, newWeek;
1167:                int max = -1;
1168:                switch (field) {
1169:                case YEAR:
1170:                    max = maximums[field];
1171:                    break;
1172:                case WEEK_OF_YEAR:
1173:                    days = daysInYear(fields[YEAR]);
1174:                    day = DAY_OF_YEAR;
1175:                    mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1176:                            - (getFirstDayOfWeek() - 1));
1177:                    maxWeeks = (days - 1 + mod) / 7 + 1;
1178:                    newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1179:                    if (newWeek == maxWeeks) {
1180:                        int addDays = (newWeek - fields[field]) * 7;
1181:                        if (fields[day] > addDays
1182:                                && fields[day] + addDays > days) {
1183:                            set(field, 1);
1184:                        } else {
1185:                            set(field, newWeek - 1);
1186:                        }
1187:                    } else if (newWeek == 1) {
1188:                        int week = (fields[day] - ((fields[day] - 1) / 7 * 7)
1189:                                - 1 + mod) / 7 + 1;
1190:                        if (week > 1) {
1191:                            set(field, 1);
1192:                        } else {
1193:                            set(field, newWeek);
1194:                        }
1195:                    } else {
1196:                        set(field, newWeek);
1197:                    }
1198:                    break;
1199:                case WEEK_OF_MONTH:
1200:                    days = daysInMonth();
1201:                    day = DATE;
1202:                    mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1203:                            - (getFirstDayOfWeek() - 1));
1204:                    maxWeeks = (days - 1 + mod) / 7 + 1;
1205:                    newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1206:                    if (newWeek == maxWeeks) {
1207:                        if (fields[day] + (newWeek - fields[field]) * 7 > days) {
1208:                            set(day, days);
1209:                        } else {
1210:                            set(field, newWeek);
1211:                        }
1212:                    } else if (newWeek == 1) {
1213:                        int week = (fields[day] - ((fields[day] - 1) / 7 * 7)
1214:                                - 1 + mod) / 7 + 1;
1215:                        if (week > 1) {
1216:                            set(day, 1);
1217:                        } else {
1218:                            set(field, newWeek);
1219:                        }
1220:                    } else {
1221:                        set(field, newWeek);
1222:                    }
1223:                    break;
1224:                case DATE:
1225:                    max = daysInMonth();
1226:                    break;
1227:                case DAY_OF_YEAR:
1228:                    max = daysInYear(fields[YEAR]);
1229:                    break;
1230:                case DAY_OF_WEEK:
1231:                    max = maximums[field];
1232:                    lastDateFieldSet = WEEK_OF_MONTH;
1233:                    break;
1234:                case DAY_OF_WEEK_IN_MONTH:
1235:                    max = (fields[DATE]
1236:                            + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
1237:                    break;
1238:
1239:                case ERA:
1240:                case MONTH:
1241:                case AM_PM:
1242:                case HOUR:
1243:                case HOUR_OF_DAY:
1244:                case MINUTE:
1245:                case SECOND:
1246:                case MILLISECOND:
1247:                    set(field, mod(fields[field] + value, maximums[field] + 1));
1248:                    if (field == MONTH && fields[DATE] > daysInMonth()) {
1249:                        set(DATE, daysInMonth());
1250:                    } else if (field == AM_PM) {
1251:                        lastTimeFieldSet = HOUR;
1252:                    }
1253:                    break;
1254:                }
1255:                if (max != -1) {
1256:                    set(field, mod(fields[field] - 1 + value, max) + 1);
1257:                }
1258:                complete();
1259:            }
1260:
1261:            /**
1262:             * Increment or decrement the specified field and wrap the value of the
1263:             * field when it goes beyond the maximum or minimum value for the current
1264:             * date. Other fields will be adjusted as required to maintain a consistent
1265:             * date. For example, March 31 will roll to April 30 when rolling the month
1266:             * field.
1267:             * 
1268:             * @param field
1269:             *            the field to roll
1270:             * @param increment
1271:             *            true to increment the field, false to decrement
1272:             * 
1273:             * @exception IllegalArgumentException
1274:             *                when an invalid field is specified
1275:             */
1276:            @Override
1277:            public void roll(int field, boolean increment) {
1278:                roll(field, increment ? 1 : -1);
1279:            }
1280:
1281:            /**
1282:             * Sets the gregorian change date of this calendar.
1283:             * 
1284:             * @param date
1285:             *            a Date which represents the gregorian change date
1286:             */
1287:            public void setGregorianChange(Date date) {
1288:                gregorianCutover = date.getTime();
1289:                GregorianCalendar cal = new GregorianCalendar(TimeZone.GMT);
1290:                cal.setTime(date);
1291:                changeYear = cal.get(YEAR);
1292:                if (cal.get(ERA) == BC) {
1293:                    changeYear = 1 - changeYear;
1294:                }
1295:                julianSkew = ((changeYear - 2000) / 400) + julianError()
1296:                        - ((changeYear - 2000) / 100);
1297:                isCached = false;
1298:                int dayOfYear = cal.get(DAY_OF_YEAR);
1299:                if (dayOfYear < julianSkew) {
1300:                    currentYearSkew = dayOfYear - 1;
1301:                    lastYearSkew = julianSkew - dayOfYear + 1;
1302:                } else {
1303:                    lastYearSkew = 0;
1304:                    currentYearSkew = julianSkew;
1305:                }
1306:                isCached = false;
1307:            }
1308:
1309:            private void writeObject(ObjectOutputStream stream)
1310:                    throws IOException {
1311:                stream.defaultWriteObject();
1312:            }
1313:
1314:            private void readObject(ObjectInputStream stream)
1315:                    throws IOException, ClassNotFoundException {
1316:
1317:                stream.defaultReadObject();
1318:                setGregorianChange(new Date(gregorianCutover));
1319:                isCached = false;
1320:            }
1321:
1322:            @Override
1323:            public void setFirstDayOfWeek(int value) {
1324:                super .setFirstDayOfWeek(value);
1325:                isCached = false;
1326:            }
1327:
1328:            @Override
1329:            public void setMinimalDaysInFirstWeek(int value) {
1330:                super .setMinimalDaysInFirstWeek(value);
1331:                isCached = false;
1332:            }
1333:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.