Source Code Cross Referenced for GJChronology.java in  » Development » Joda-Time » org » joda » time » chrono » 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 » Development » Joda Time » org.joda.time.chrono 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Copyright 2001-2005 Stephen Colebourne
0003:         *
0004:         *  Licensed under the Apache License, Version 2.0 (the "License");
0005:         *  you may not use this file except in compliance with the License.
0006:         *  You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         *  Unless required by applicable law or agreed to in writing, software
0011:         *  distributed under the License is distributed on an "AS IS" BASIS,
0012:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         *  See the License for the specific language governing permissions and
0014:         *  limitations under the License.
0015:         */
0016:        package org.joda.time.chrono;
0017:
0018:        import java.util.ArrayList;
0019:        import java.util.HashMap;
0020:        import java.util.Locale;
0021:        import java.util.Map;
0022:
0023:        import org.joda.time.Chronology;
0024:        import org.joda.time.DateTimeField;
0025:        import org.joda.time.DateTimeUtils;
0026:        import org.joda.time.DateTimeZone;
0027:        import org.joda.time.DurationField;
0028:        import org.joda.time.IllegalFieldValueException;
0029:        import org.joda.time.Instant;
0030:        import org.joda.time.ReadableInstant;
0031:        import org.joda.time.ReadablePartial;
0032:        import org.joda.time.field.BaseDateTimeField;
0033:        import org.joda.time.field.DecoratedDurationField;
0034:        import org.joda.time.format.DateTimeFormatter;
0035:        import org.joda.time.format.ISODateTimeFormat;
0036:
0037:        /**
0038:         * Implements the Gregorian/Julian calendar system which is the calendar system
0039:         * used in most of the world. Wherever possible, it is recommended to use the
0040:         * {@link ISOChronology} instead.
0041:         * <p>
0042:         * The Gregorian calendar replaced the Julian calendar, and the point in time
0043:         * when this chronology switches can be controlled using the second parameter
0044:         * of the getInstance method. By default this cutover is set to the date the
0045:         * Gregorian calendar was first instituted, October 15, 1582.
0046:         * <p>
0047:         * Before this date, this chronology uses the proleptic Julian calendar
0048:         * (proleptic means extending indefinitely). The Julian calendar has leap years
0049:         * every four years, whereas the Gregorian has special rules for 100 and 400
0050:         * years. A meaningful result will thus be obtained for all input values.
0051:         * However before 8 CE, Julian leap years were irregular, and before 45 BCE
0052:         * there was no Julian calendar.
0053:         * <p>
0054:         * This chronology differs from
0055:         * {@link java.util.GregorianCalendar GregorianCalendar} in that years
0056:         * in BCE are returned correctly. Thus year 1 BCE is returned as -1 instead of 1.
0057:         * The yearOfEra field produces results compatible with GregorianCalendar.
0058:         * <p>
0059:         * The Julian calendar does not have a year zero, and so year -1 is followed by
0060:         * year 1. If the Gregorian cutover date is specified at or before year -1
0061:         * (Julian), year zero is defined. In other words, the proleptic Gregorian
0062:         * chronology used by this class has a year zero.
0063:         * <p>
0064:         * To create a pure proleptic Julian chronology, use {@link JulianChronology},
0065:         * and to create a pure proleptic Gregorian chronology, use
0066:         * {@link GregorianChronology}.
0067:         * <p>
0068:         * GJChronology is thread-safe and immutable.
0069:         * 
0070:         * @author Brian S O'Neill
0071:         * @author Stephen Colebourne
0072:         * @since 1.0
0073:         */
0074:        public final class GJChronology extends AssembledChronology {
0075:
0076:            /** Serialization lock */
0077:            private static final long serialVersionUID = -2545574827706931671L;
0078:
0079:            /**
0080:             * Convert a datetime from one chronology to another.
0081:             */
0082:            private static long convertByYear(long instant, Chronology from,
0083:                    Chronology to) {
0084:                return to.getDateTimeMillis(from.year().get(instant), from
0085:                        .monthOfYear().get(instant), from.dayOfMonth().get(
0086:                        instant), from.millisOfDay().get(instant));
0087:            }
0088:
0089:            /**
0090:             * Convert a datetime from one chronology to another.
0091:             */
0092:            private static long convertByWeekyear(final long instant,
0093:                    Chronology from, Chronology to) {
0094:                long newInstant;
0095:                newInstant = to.weekyear().set(0, from.weekyear().get(instant));
0096:                newInstant = to.weekOfWeekyear().set(newInstant,
0097:                        from.weekOfWeekyear().get(instant));
0098:                newInstant = to.dayOfWeek().set(newInstant,
0099:                        from.dayOfWeek().get(instant));
0100:                newInstant = to.millisOfDay().set(newInstant,
0101:                        from.millisOfDay().get(instant));
0102:                return newInstant;
0103:            }
0104:
0105:            /**
0106:             * The default GregorianJulian cutover point.
0107:             */
0108:            static final Instant DEFAULT_CUTOVER = new Instant(-12219292800000L);
0109:
0110:            /** Cache of zone to chronology list */
0111:            private static final Map cCache = new HashMap();
0112:
0113:            /**
0114:             * Factory method returns instances of the default GJ cutover
0115:             * chronology. This uses a cutover date of October 15, 1582 (Gregorian)
0116:             * 00:00:00 UTC. For this value, October 4, 1582 (Julian) is followed by
0117:             * October 15, 1582 (Gregorian).
0118:             *
0119:             * <p>The first day of the week is designated to be
0120:             * {@link org.joda.time.DateTimeConstants#MONDAY Monday},
0121:             * and the minimum days in the first week of the year is 4.
0122:             *
0123:             * <p>The time zone of the returned instance is UTC.
0124:             */
0125:            public static GJChronology getInstanceUTC() {
0126:                return getInstance(DateTimeZone.UTC, DEFAULT_CUTOVER, 4);
0127:            }
0128:
0129:            /**
0130:             * Factory method returns instances of the default GJ cutover
0131:             * chronology. This uses a cutover date of October 15, 1582 (Gregorian)
0132:             * 00:00:00 UTC. For this value, October 4, 1582 (Julian) is followed by
0133:             * October 15, 1582 (Gregorian).
0134:             *
0135:             * <p>The first day of the week is designated to be
0136:             * {@link org.joda.time.DateTimeConstants#MONDAY Monday},
0137:             * and the minimum days in the first week of the year is 4.
0138:             *
0139:             * <p>The returned chronology is in the default time zone.
0140:             */
0141:            public static GJChronology getInstance() {
0142:                return getInstance(DateTimeZone.getDefault(), DEFAULT_CUTOVER,
0143:                        4);
0144:            }
0145:
0146:            /**
0147:             * Factory method returns instances of the GJ cutover chronology. This uses
0148:             * a cutover date of October 15, 1582 (Gregorian) 00:00:00 UTC. For this
0149:             * value, October 4, 1582 (Julian) is followed by October 15, 1582
0150:             * (Gregorian).
0151:             *
0152:             * <p>The first day of the week is designated to be
0153:             * {@link org.joda.time.DateTimeConstants#MONDAY Monday},
0154:             * and the minimum days in the first week of the year is 4.
0155:             *
0156:             * @param zone  the time zone to use, null is default
0157:             */
0158:            public static GJChronology getInstance(DateTimeZone zone) {
0159:                return getInstance(zone, DEFAULT_CUTOVER, 4);
0160:            }
0161:
0162:            /**
0163:             * Factory method returns instances of the GJ cutover chronology. Any
0164:             * cutover date may be specified.
0165:             *
0166:             * <p>The first day of the week is designated to be
0167:             * {@link org.joda.time.DateTimeConstants#MONDAY Monday},
0168:             * and the minimum days in the first week of the year is 4.
0169:             *
0170:             * @param zone  the time zone to use, null is default
0171:             * @param gregorianCutover  the cutover to use, null means default
0172:             */
0173:            public static GJChronology getInstance(DateTimeZone zone,
0174:                    ReadableInstant gregorianCutover) {
0175:
0176:                return getInstance(zone, gregorianCutover, 4);
0177:            }
0178:
0179:            /**
0180:             * Factory method returns instances of the GJ cutover chronology. Any
0181:             * cutover date may be specified.
0182:             *
0183:             * @param zone  the time zone to use, null is default
0184:             * @param gregorianCutover  the cutover to use, null means default
0185:             * @param minDaysInFirstWeek  minimum number of days in first week of the year; default is 4
0186:             */
0187:            public static synchronized GJChronology getInstance(
0188:                    DateTimeZone zone, ReadableInstant gregorianCutover,
0189:                    int minDaysInFirstWeek) {
0190:
0191:                zone = DateTimeUtils.getZone(zone);
0192:                Instant cutoverInstant;
0193:                if (gregorianCutover == null) {
0194:                    cutoverInstant = DEFAULT_CUTOVER;
0195:                } else {
0196:                    cutoverInstant = gregorianCutover.toInstant();
0197:                }
0198:
0199:                GJChronology chrono;
0200:
0201:                ArrayList chronos = (ArrayList) cCache.get(zone);
0202:                if (chronos == null) {
0203:                    chronos = new ArrayList(2);
0204:                    cCache.put(zone, chronos);
0205:                } else {
0206:                    for (int i = chronos.size(); --i >= 0;) {
0207:                        chrono = (GJChronology) chronos.get(i);
0208:                        if (minDaysInFirstWeek == chrono
0209:                                .getMinimumDaysInFirstWeek()
0210:                                && cutoverInstant.equals(chrono
0211:                                        .getGregorianCutover())) {
0212:
0213:                            return chrono;
0214:                        }
0215:                    }
0216:                }
0217:
0218:                if (zone == DateTimeZone.UTC) {
0219:                    chrono = new GJChronology(JulianChronology.getInstance(
0220:                            zone, minDaysInFirstWeek), GregorianChronology
0221:                            .getInstance(zone, minDaysInFirstWeek),
0222:                            cutoverInstant);
0223:                } else {
0224:                    chrono = getInstance(DateTimeZone.UTC, cutoverInstant,
0225:                            minDaysInFirstWeek);
0226:                    chrono = new GJChronology(ZonedChronology.getInstance(
0227:                            chrono, zone), chrono.iJulianChronology,
0228:                            chrono.iGregorianChronology, chrono.iCutoverInstant);
0229:                }
0230:
0231:                chronos.add(chrono);
0232:
0233:                return chrono;
0234:            }
0235:
0236:            /**
0237:             * Factory method returns instances of the GJ cutover chronology. Any
0238:             * cutover date may be specified.
0239:             *
0240:             * @param zone  the time zone to use, null is default
0241:             * @param gregorianCutover  the cutover to use
0242:             * @param minDaysInFirstWeek  minimum number of days in first week of the year; default is 4
0243:             */
0244:            public static GJChronology getInstance(DateTimeZone zone,
0245:                    long gregorianCutover, int minDaysInFirstWeek) {
0246:
0247:                Instant cutoverInstant;
0248:                if (gregorianCutover == DEFAULT_CUTOVER.getMillis()) {
0249:                    cutoverInstant = null;
0250:                } else {
0251:                    cutoverInstant = new Instant(gregorianCutover);
0252:                }
0253:                return getInstance(zone, cutoverInstant, minDaysInFirstWeek);
0254:            }
0255:
0256:            //-----------------------------------------------------------------------
0257:            private JulianChronology iJulianChronology;
0258:            private GregorianChronology iGregorianChronology;
0259:            private Instant iCutoverInstant;
0260:
0261:            private long iCutoverMillis;
0262:            private long iGapDuration;
0263:
0264:            /**
0265:             * @param julian chronology used before the cutover instant
0266:             * @param gregorian chronology used at and after the cutover instant
0267:             * @param cutoverInstant instant when the gregorian chronology began
0268:             */
0269:            private GJChronology(JulianChronology julian,
0270:                    GregorianChronology gregorian, Instant cutoverInstant) {
0271:                super (null, new Object[] { julian, gregorian, cutoverInstant });
0272:            }
0273:
0274:            /**
0275:             * Called when applying a time zone.
0276:             */
0277:            private GJChronology(Chronology base, JulianChronology julian,
0278:                    GregorianChronology gregorian, Instant cutoverInstant) {
0279:                super (base, new Object[] { julian, gregorian, cutoverInstant });
0280:            }
0281:
0282:            /**
0283:             * Serialization singleton
0284:             */
0285:            private Object readResolve() {
0286:                return getInstance(getZone(), iCutoverInstant,
0287:                        getMinimumDaysInFirstWeek());
0288:            }
0289:
0290:            public DateTimeZone getZone() {
0291:                Chronology base;
0292:                if ((base = getBase()) != null) {
0293:                    return base.getZone();
0294:                }
0295:                return DateTimeZone.UTC;
0296:            }
0297:
0298:            // Conversion
0299:            //-----------------------------------------------------------------------
0300:            /**
0301:             * Gets the Chronology in the UTC time zone.
0302:             * 
0303:             * @return the chronology in UTC
0304:             */
0305:            public Chronology withUTC() {
0306:                return withZone(DateTimeZone.UTC);
0307:            }
0308:
0309:            /**
0310:             * Gets the Chronology in a specific time zone.
0311:             * 
0312:             * @param zone  the zone to get the chronology in, null is default
0313:             * @return the chronology
0314:             */
0315:            public Chronology withZone(DateTimeZone zone) {
0316:                if (zone == null) {
0317:                    zone = DateTimeZone.getDefault();
0318:                }
0319:                if (zone == getZone()) {
0320:                    return this ;
0321:                }
0322:                return getInstance(zone, iCutoverInstant,
0323:                        getMinimumDaysInFirstWeek());
0324:            }
0325:
0326:            public long getDateTimeMillis(int year, int monthOfYear,
0327:                    int dayOfMonth, int millisOfDay)
0328:                    throws IllegalArgumentException {
0329:                Chronology base;
0330:                if ((base = getBase()) != null) {
0331:                    return base.getDateTimeMillis(year, monthOfYear,
0332:                            dayOfMonth, millisOfDay);
0333:                }
0334:
0335:                // Assume date is Gregorian.
0336:                long instant = iGregorianChronology.getDateTimeMillis(year,
0337:                        monthOfYear, dayOfMonth, millisOfDay);
0338:                if (instant < iCutoverMillis) {
0339:                    // Maybe it's Julian.
0340:                    instant = iJulianChronology.getDateTimeMillis(year,
0341:                            monthOfYear, dayOfMonth, millisOfDay);
0342:                    if (instant >= iCutoverMillis) {
0343:                        // Okay, it's in the illegal cutover gap.
0344:                        throw new IllegalArgumentException(
0345:                                "Specified date does not exist");
0346:                    }
0347:                }
0348:                return instant;
0349:            }
0350:
0351:            public long getDateTimeMillis(int year, int monthOfYear,
0352:                    int dayOfMonth, int hourOfDay, int minuteOfHour,
0353:                    int secondOfMinute, int millisOfSecond)
0354:                    throws IllegalArgumentException {
0355:                Chronology base;
0356:                if ((base = getBase()) != null) {
0357:                    return base.getDateTimeMillis(year, monthOfYear,
0358:                            dayOfMonth, hourOfDay, minuteOfHour,
0359:                            secondOfMinute, millisOfSecond);
0360:                }
0361:
0362:                // Assume date is Gregorian.
0363:                long instant = iGregorianChronology.getDateTimeMillis(year,
0364:                        monthOfYear, dayOfMonth, hourOfDay, minuteOfHour,
0365:                        secondOfMinute, millisOfSecond);
0366:                if (instant < iCutoverMillis) {
0367:                    // Maybe it's Julian.
0368:                    instant = iJulianChronology.getDateTimeMillis(year,
0369:                            monthOfYear, dayOfMonth, hourOfDay, minuteOfHour,
0370:                            secondOfMinute, millisOfSecond);
0371:                    if (instant >= iCutoverMillis) {
0372:                        // Okay, it's in the illegal cutover gap.
0373:                        throw new IllegalArgumentException(
0374:                                "Specified date does not exist");
0375:                    }
0376:                }
0377:                return instant;
0378:            }
0379:
0380:            /**
0381:             * Gets the cutover instant between Gregorian and Julian chronologies.
0382:             * @return the cutover instant
0383:             */
0384:            public Instant getGregorianCutover() {
0385:                return iCutoverInstant;
0386:            }
0387:
0388:            /**
0389:             * Gets the minimum days needed for a week to be the first week in a year.
0390:             * 
0391:             * @return the minimum days
0392:             */
0393:            public int getMinimumDaysInFirstWeek() {
0394:                return iGregorianChronology.getMinimumDaysInFirstWeek();
0395:            }
0396:
0397:            // Output
0398:            //-----------------------------------------------------------------------
0399:            /**
0400:             * Gets a debugging toString.
0401:             * 
0402:             * @return a debugging string
0403:             */
0404:            public String toString() {
0405:                StringBuffer sb = new StringBuffer(60);
0406:                sb.append("GJChronology");
0407:                sb.append('[');
0408:                sb.append(getZone().getID());
0409:
0410:                if (iCutoverMillis != DEFAULT_CUTOVER.getMillis()) {
0411:                    sb.append(",cutover=");
0412:                    DateTimeFormatter printer;
0413:                    if (withUTC().dayOfYear().remainder(iCutoverMillis) == 0) {
0414:                        printer = ISODateTimeFormat.date();
0415:                    } else {
0416:                        printer = ISODateTimeFormat.dateTime();
0417:                    }
0418:                    printer.withChronology(withUTC()).printTo(sb,
0419:                            iCutoverMillis);
0420:                }
0421:
0422:                if (getMinimumDaysInFirstWeek() != 4) {
0423:                    sb.append(",mdfw=");
0424:                    sb.append(getMinimumDaysInFirstWeek());
0425:                }
0426:                sb.append(']');
0427:
0428:                return sb.toString();
0429:            }
0430:
0431:            protected void assemble(Fields fields) {
0432:                Object[] params = (Object[]) getParam();
0433:
0434:                JulianChronology julian = (JulianChronology) params[0];
0435:                GregorianChronology gregorian = (GregorianChronology) params[1];
0436:                Instant cutoverInstant = (Instant) params[2];
0437:                iCutoverMillis = cutoverInstant.getMillis();
0438:
0439:                iJulianChronology = julian;
0440:                iGregorianChronology = gregorian;
0441:                iCutoverInstant = cutoverInstant;
0442:
0443:                if (getBase() != null) {
0444:                    return;
0445:                }
0446:
0447:                if (julian.getMinimumDaysInFirstWeek() != gregorian
0448:                        .getMinimumDaysInFirstWeek()) {
0449:                    throw new IllegalArgumentException();
0450:                }
0451:
0452:                // Compute difference between the chronologies at the cutover instant
0453:                iGapDuration = iCutoverMillis
0454:                        - julianToGregorianByYear(iCutoverMillis);
0455:
0456:                // Begin field definitions.
0457:
0458:                // First just copy all the Gregorian fields and then override those
0459:                // that need special attention.
0460:                fields.copyFieldsFrom(gregorian);
0461:
0462:                // Assuming cutover is at midnight, all time of day fields can be
0463:                // gregorian since they are unaffected by cutover.
0464:
0465:                // Verify assumption.
0466:                if (gregorian.millisOfDay().get(iCutoverMillis) == 0) {
0467:                    // Cutover is sometime in the day, so cutover fields are required
0468:                    // for time of day.
0469:
0470:                    fields.millisOfSecond = new CutoverField(julian
0471:                            .millisOfSecond(), fields.millisOfSecond,
0472:                            iCutoverMillis);
0473:                    fields.millisOfDay = new CutoverField(julian.millisOfDay(),
0474:                            fields.millisOfDay, iCutoverMillis);
0475:                    fields.secondOfMinute = new CutoverField(julian
0476:                            .secondOfMinute(), fields.secondOfMinute,
0477:                            iCutoverMillis);
0478:                    fields.secondOfDay = new CutoverField(julian.secondOfDay(),
0479:                            fields.secondOfDay, iCutoverMillis);
0480:                    fields.minuteOfHour = new CutoverField(julian
0481:                            .minuteOfHour(), fields.minuteOfHour,
0482:                            iCutoverMillis);
0483:                    fields.minuteOfDay = new CutoverField(julian.minuteOfDay(),
0484:                            fields.minuteOfDay, iCutoverMillis);
0485:                    fields.hourOfDay = new CutoverField(julian.hourOfDay(),
0486:                            fields.hourOfDay, iCutoverMillis);
0487:                    fields.hourOfHalfday = new CutoverField(julian
0488:                            .hourOfHalfday(), fields.hourOfHalfday,
0489:                            iCutoverMillis);
0490:                    fields.clockhourOfDay = new CutoverField(julian
0491:                            .clockhourOfDay(), fields.clockhourOfDay,
0492:                            iCutoverMillis);
0493:                    fields.clockhourOfHalfday = new CutoverField(julian
0494:                            .clockhourOfHalfday(), fields.clockhourOfHalfday,
0495:                            iCutoverMillis);
0496:                    fields.halfdayOfDay = new CutoverField(julian
0497:                            .halfdayOfDay(), fields.halfdayOfDay,
0498:                            iCutoverMillis);
0499:                }
0500:
0501:                // These fields just require basic cutover support.
0502:                {
0503:                    fields.era = new CutoverField(julian.era(), fields.era,
0504:                            iCutoverMillis);
0505:                }
0506:
0507:                // DayOfYear and weekOfWeekyear require special handling since cutover
0508:                // year has fewer days and weeks. Extend the cutover to the start of
0509:                // the next year or weekyear. This keeps the sequence unbroken during
0510:                // the cutover year.
0511:
0512:                {
0513:                    long cutover = gregorian.year()
0514:                            .roundCeiling(iCutoverMillis);
0515:                    fields.dayOfYear = new CutoverField(julian.dayOfYear(),
0516:                            fields.dayOfYear, cutover);
0517:                }
0518:
0519:                {
0520:                    long cutover = gregorian.weekyear().roundCeiling(
0521:                            iCutoverMillis);
0522:                    fields.weekOfWeekyear = new CutoverField(julian
0523:                            .weekOfWeekyear(), fields.weekOfWeekyear, cutover,
0524:                            true);
0525:                }
0526:
0527:                // These fields are special because they have imprecise durations. The
0528:                // family of addition methods need special attention. Override affected
0529:                // duration fields as well.
0530:                {
0531:                    fields.year = new ImpreciseCutoverField(julian.year(),
0532:                            fields.year, iCutoverMillis);
0533:                    fields.years = fields.year.getDurationField();
0534:                    fields.yearOfEra = new ImpreciseCutoverField(julian
0535:                            .yearOfEra(), fields.yearOfEra, fields.years,
0536:                            iCutoverMillis);
0537:                    fields.yearOfCentury = new ImpreciseCutoverField(julian
0538:                            .yearOfCentury(), fields.yearOfCentury,
0539:                            fields.years, iCutoverMillis);
0540:
0541:                    fields.centuryOfEra = new ImpreciseCutoverField(julian
0542:                            .centuryOfEra(), fields.centuryOfEra,
0543:                            iCutoverMillis);
0544:                    fields.centuries = fields.centuryOfEra.getDurationField();
0545:
0546:                    fields.monthOfYear = new ImpreciseCutoverField(julian
0547:                            .monthOfYear(), fields.monthOfYear, iCutoverMillis);
0548:                    fields.months = fields.monthOfYear.getDurationField();
0549:
0550:                    fields.weekyear = new ImpreciseCutoverField(julian
0551:                            .weekyear(), fields.weekyear, null, iCutoverMillis,
0552:                            true);
0553:                    fields.weekyearOfCentury = new ImpreciseCutoverField(julian
0554:                            .weekyearOfCentury(), fields.weekyearOfCentury,
0555:                            fields.weekyears, iCutoverMillis);
0556:                    fields.weekyears = fields.weekyear.getDurationField();
0557:                }
0558:
0559:                // These fields require basic cutover support, except they must link to
0560:                // imprecise durations.
0561:                {
0562:                    CutoverField cf = new CutoverField(julian.dayOfMonth(),
0563:                            fields.dayOfMonth, iCutoverMillis);
0564:                    cf.iRangeDurationField = fields.months;
0565:                    fields.dayOfMonth = cf;
0566:                }
0567:            }
0568:
0569:            long julianToGregorianByYear(long instant) {
0570:                return convertByYear(instant, iJulianChronology,
0571:                        iGregorianChronology);
0572:            }
0573:
0574:            long gregorianToJulianByYear(long instant) {
0575:                return convertByYear(instant, iGregorianChronology,
0576:                        iJulianChronology);
0577:            }
0578:
0579:            long julianToGregorianByWeekyear(long instant) {
0580:                return convertByWeekyear(instant, iJulianChronology,
0581:                        iGregorianChronology);
0582:            }
0583:
0584:            long gregorianToJulianByWeekyear(long instant) {
0585:                return convertByWeekyear(instant, iGregorianChronology,
0586:                        iJulianChronology);
0587:            }
0588:
0589:            //-----------------------------------------------------------------------
0590:            /**
0591:             * This basic cutover field adjusts calls to 'get' and 'set' methods, and
0592:             * assumes that calls to add and addWrapField are unaffected by the cutover.
0593:             */
0594:            private class CutoverField extends BaseDateTimeField {
0595:                private static final long serialVersionUID = 3528501219481026402L;
0596:
0597:                final DateTimeField iJulianField;
0598:                final DateTimeField iGregorianField;
0599:                final long iCutover;
0600:                final boolean iConvertByWeekyear;
0601:
0602:                protected DurationField iDurationField;
0603:                protected DurationField iRangeDurationField;
0604:
0605:                /**
0606:                 * @param julianField field from the chronology used before the cutover instant
0607:                 * @param gregorianField field from the chronology used at and after the cutover
0608:                 * @param cutoverMillis  the millis of the cutover
0609:                 */
0610:                CutoverField(DateTimeField julianField,
0611:                        DateTimeField gregorianField, long cutoverMillis) {
0612:                    this (julianField, gregorianField, cutoverMillis, false);
0613:                }
0614:
0615:                /**
0616:                 * @param julianField field from the chronology used before the cutover instant
0617:                 * @param gregorianField field from the chronology used at and after the cutover
0618:                 * @param cutoverMillis  the millis of the cutover
0619:                 * @param convertByWeekyear
0620:                 */
0621:                CutoverField(DateTimeField julianField,
0622:                        DateTimeField gregorianField, long cutoverMillis,
0623:                        boolean convertByWeekyear) {
0624:                    super (gregorianField.getType());
0625:                    iJulianField = julianField;
0626:                    iGregorianField = gregorianField;
0627:                    iCutover = cutoverMillis;
0628:                    iConvertByWeekyear = convertByWeekyear;
0629:                    // Although average length of Julian and Gregorian years differ,
0630:                    // use the Gregorian duration field because it is more accurate.
0631:                    iDurationField = gregorianField.getDurationField();
0632:
0633:                    DurationField rangeField = gregorianField
0634:                            .getRangeDurationField();
0635:                    if (rangeField == null) {
0636:                        rangeField = julianField.getRangeDurationField();
0637:                    }
0638:                    iRangeDurationField = rangeField;
0639:                }
0640:
0641:                public boolean isLenient() {
0642:                    return false;
0643:                }
0644:
0645:                public int get(long instant) {
0646:                    if (instant >= iCutover) {
0647:                        return iGregorianField.get(instant);
0648:                    } else {
0649:                        return iJulianField.get(instant);
0650:                    }
0651:                }
0652:
0653:                public String getAsText(long instant, Locale locale) {
0654:                    if (instant >= iCutover) {
0655:                        return iGregorianField.getAsText(instant, locale);
0656:                    } else {
0657:                        return iJulianField.getAsText(instant, locale);
0658:                    }
0659:                }
0660:
0661:                public String getAsText(int fieldValue, Locale locale) {
0662:                    return iGregorianField.getAsText(fieldValue, locale);
0663:                }
0664:
0665:                public String getAsShortText(long instant, Locale locale) {
0666:                    if (instant >= iCutover) {
0667:                        return iGregorianField.getAsShortText(instant, locale);
0668:                    } else {
0669:                        return iJulianField.getAsShortText(instant, locale);
0670:                    }
0671:                }
0672:
0673:                public String getAsShortText(int fieldValue, Locale locale) {
0674:                    return iGregorianField.getAsShortText(fieldValue, locale);
0675:                }
0676:
0677:                public long add(long instant, int value) {
0678:                    return iGregorianField.add(instant, value);
0679:                }
0680:
0681:                public long add(long instant, long value) {
0682:                    return iGregorianField.add(instant, value);
0683:                }
0684:
0685:                public int[] add(ReadablePartial partial, int fieldIndex,
0686:                        int[] values, int valueToAdd) {
0687:                    // overridden as superclass algorithm can't handle
0688:                    // 2004-02-29 + 48 months -> 2008-02-29 type dates
0689:                    if (valueToAdd == 0) {
0690:                        return values;
0691:                    }
0692:                    if (DateTimeUtils.isContiguous(partial)) {
0693:                        long instant = 0L;
0694:                        for (int i = 0, isize = partial.size(); i < isize; i++) {
0695:                            instant = partial.getFieldType(i).getField(
0696:                                    GJChronology.this ).set(instant, values[i]);
0697:                        }
0698:                        instant = add(instant, valueToAdd);
0699:                        return GJChronology.this .get(partial, instant);
0700:                    } else {
0701:                        return super .add(partial, fieldIndex, values,
0702:                                valueToAdd);
0703:                    }
0704:                }
0705:
0706:                public int getDifference(long minuendInstant,
0707:                        long subtrahendInstant) {
0708:                    return iGregorianField.getDifference(minuendInstant,
0709:                            subtrahendInstant);
0710:                }
0711:
0712:                public long getDifferenceAsLong(long minuendInstant,
0713:                        long subtrahendInstant) {
0714:                    return iGregorianField.getDifferenceAsLong(minuendInstant,
0715:                            subtrahendInstant);
0716:                }
0717:
0718:                public long set(long instant, int value) {
0719:                    if (instant >= iCutover) {
0720:                        instant = iGregorianField.set(instant, value);
0721:                        if (instant < iCutover) {
0722:                            // Only adjust if gap fully crossed.
0723:                            if (instant + iGapDuration < iCutover) {
0724:                                instant = gregorianToJulian(instant);
0725:                            }
0726:                            // Verify that new value stuck.
0727:                            if (get(instant) != value) {
0728:                                throw new IllegalFieldValueException(
0729:                                        iGregorianField.getType(), new Integer(
0730:                                                value), null, null);
0731:                            }
0732:                        }
0733:                    } else {
0734:                        instant = iJulianField.set(instant, value);
0735:                        if (instant >= iCutover) {
0736:                            // Only adjust if gap fully crossed.
0737:                            if (instant - iGapDuration >= iCutover) {
0738:                                instant = julianToGregorian(instant);
0739:                            }
0740:                            // Verify that new value stuck.
0741:                            if (get(instant) != value) {
0742:                                throw new IllegalFieldValueException(
0743:                                        iJulianField.getType(), new Integer(
0744:                                                value), null, null);
0745:                            }
0746:                        }
0747:                    }
0748:                    return instant;
0749:                }
0750:
0751:                public long set(long instant, String text, Locale locale) {
0752:                    if (instant >= iCutover) {
0753:                        instant = iGregorianField.set(instant, text, locale);
0754:                        if (instant < iCutover) {
0755:                            // Only adjust if gap fully crossed.
0756:                            if (instant + iGapDuration < iCutover) {
0757:                                instant = gregorianToJulian(instant);
0758:                            }
0759:                            // Cannot verify that new value stuck because set may be lenient.
0760:                        }
0761:                    } else {
0762:                        instant = iJulianField.set(instant, text, locale);
0763:                        if (instant >= iCutover) {
0764:                            // Only adjust if gap fully crossed.
0765:                            if (instant - iGapDuration >= iCutover) {
0766:                                instant = julianToGregorian(instant);
0767:                            }
0768:                            // Cannot verify that new value stuck because set may be lenient.
0769:                        }
0770:                    }
0771:                    return instant;
0772:                }
0773:
0774:                public DurationField getDurationField() {
0775:                    return iDurationField;
0776:                }
0777:
0778:                public DurationField getRangeDurationField() {
0779:                    return iRangeDurationField;
0780:                }
0781:
0782:                public boolean isLeap(long instant) {
0783:                    if (instant >= iCutover) {
0784:                        return iGregorianField.isLeap(instant);
0785:                    } else {
0786:                        return iJulianField.isLeap(instant);
0787:                    }
0788:                }
0789:
0790:                public int getLeapAmount(long instant) {
0791:                    if (instant >= iCutover) {
0792:                        return iGregorianField.getLeapAmount(instant);
0793:                    } else {
0794:                        return iJulianField.getLeapAmount(instant);
0795:                    }
0796:                }
0797:
0798:                public DurationField getLeapDurationField() {
0799:                    return iGregorianField.getLeapDurationField();
0800:                }
0801:
0802:                public int getMinimumValue() {
0803:                    // For all precise fields, the Julian and Gregorian limits are
0804:                    // identical. Choose Julian to tighten up the year limits.
0805:                    return iJulianField.getMinimumValue();
0806:                }
0807:
0808:                public int getMinimumValue(ReadablePartial partial) {
0809:                    return iJulianField.getMinimumValue(partial);
0810:                }
0811:
0812:                public int getMinimumValue(ReadablePartial partial, int[] values) {
0813:                    return iJulianField.getMinimumValue(partial, values);
0814:                }
0815:
0816:                public int getMinimumValue(long instant) {
0817:                    if (instant < iCutover) {
0818:                        return iJulianField.getMinimumValue(instant);
0819:                    }
0820:
0821:                    int min = iGregorianField.getMinimumValue(instant);
0822:
0823:                    // Because the cutover may reduce the length of this field, verify
0824:                    // the minimum by setting it.
0825:                    instant = iGregorianField.set(instant, min);
0826:                    if (instant < iCutover) {
0827:                        min = iGregorianField.get(iCutover);
0828:                    }
0829:
0830:                    return min;
0831:                }
0832:
0833:                public int getMaximumValue() {
0834:                    // For all precise fields, the Julian and Gregorian limits are
0835:                    // identical.
0836:                    return iGregorianField.getMaximumValue();
0837:                }
0838:
0839:                public int getMaximumValue(long instant) {
0840:                    if (instant >= iCutover) {
0841:                        return iGregorianField.getMaximumValue(instant);
0842:                    }
0843:
0844:                    int max = iJulianField.getMaximumValue(instant);
0845:
0846:                    // Because the cutover may reduce the length of this field, verify
0847:                    // the maximum by setting it.
0848:                    instant = iJulianField.set(instant, max);
0849:                    if (instant >= iCutover) {
0850:                        max = iJulianField.get(iJulianField.add(iCutover, -1));
0851:                    }
0852:
0853:                    return max;
0854:                }
0855:
0856:                public int getMaximumValue(ReadablePartial partial) {
0857:                    long instant = GJChronology.getInstanceUTC().set(partial,
0858:                            0L);
0859:                    return getMaximumValue(instant);
0860:                }
0861:
0862:                public int getMaximumValue(ReadablePartial partial, int[] values) {
0863:                    Chronology chrono = GJChronology.getInstanceUTC();
0864:                    long instant = 0L;
0865:                    for (int i = 0, isize = partial.size(); i < isize; i++) {
0866:                        DateTimeField field = partial.getFieldType(i).getField(
0867:                                chrono);
0868:                        if (values[i] <= field.getMaximumValue(instant)) {
0869:                            instant = field.set(instant, values[i]);
0870:                        }
0871:                    }
0872:                    return getMaximumValue(instant);
0873:                }
0874:
0875:                public long roundFloor(long instant) {
0876:                    if (instant >= iCutover) {
0877:                        instant = iGregorianField.roundFloor(instant);
0878:                        if (instant < iCutover) {
0879:                            // Only adjust if gap fully crossed.
0880:                            if (instant + iGapDuration < iCutover) {
0881:                                instant = gregorianToJulian(instant);
0882:                            }
0883:                        }
0884:                    } else {
0885:                        instant = iJulianField.roundFloor(instant);
0886:                    }
0887:                    return instant;
0888:                }
0889:
0890:                public long roundCeiling(long instant) {
0891:                    if (instant >= iCutover) {
0892:                        instant = iGregorianField.roundCeiling(instant);
0893:                    } else {
0894:                        instant = iJulianField.roundCeiling(instant);
0895:                        if (instant >= iCutover) {
0896:                            // Only adjust if gap fully crossed.
0897:                            if (instant - iGapDuration >= iCutover) {
0898:                                instant = julianToGregorian(instant);
0899:                            }
0900:                        }
0901:                    }
0902:                    return instant;
0903:                }
0904:
0905:                public int getMaximumTextLength(Locale locale) {
0906:                    return Math.max(iJulianField.getMaximumTextLength(locale),
0907:                            iGregorianField.getMaximumTextLength(locale));
0908:                }
0909:
0910:                public int getMaximumShortTextLength(Locale locale) {
0911:                    return Math.max(iJulianField
0912:                            .getMaximumShortTextLength(locale), iGregorianField
0913:                            .getMaximumShortTextLength(locale));
0914:                }
0915:
0916:                protected long julianToGregorian(long instant) {
0917:                    if (iConvertByWeekyear) {
0918:                        return julianToGregorianByWeekyear(instant);
0919:                    } else {
0920:                        return julianToGregorianByYear(instant);
0921:                    }
0922:                }
0923:
0924:                protected long gregorianToJulian(long instant) {
0925:                    if (iConvertByWeekyear) {
0926:                        return gregorianToJulianByWeekyear(instant);
0927:                    } else {
0928:                        return gregorianToJulianByYear(instant);
0929:                    }
0930:                }
0931:            }
0932:
0933:            //-----------------------------------------------------------------------
0934:            /**
0935:             * Cutover field for variable length fields. These fields internally call
0936:             * set whenever add is called. As a result, the same correction applied to
0937:             * set must be applied to add and addWrapField. Knowing when to use this
0938:             * field requires specific knowledge of how the GJ fields are implemented.
0939:             */
0940:            private final class ImpreciseCutoverField extends CutoverField {
0941:                private static final long serialVersionUID = 3410248757173576441L;
0942:
0943:                /**
0944:                 * Creates a duration field that links back to this.
0945:                 */
0946:                ImpreciseCutoverField(DateTimeField julianField,
0947:                        DateTimeField gregorianField, long cutoverMillis) {
0948:                    this (julianField, gregorianField, null, cutoverMillis,
0949:                            false);
0950:                }
0951:
0952:                /**
0953:                 * Uses a shared duration field rather than creating a new one.
0954:                 *
0955:                 * @param durationField shared duration field
0956:                 */
0957:                ImpreciseCutoverField(DateTimeField julianField,
0958:                        DateTimeField gregorianField,
0959:                        DurationField durationField, long cutoverMillis) {
0960:                    this (julianField, gregorianField, durationField,
0961:                            cutoverMillis, false);
0962:                }
0963:
0964:                /**
0965:                 * Uses a shared duration field rather than creating a new one.
0966:                 *
0967:                 * @param durationField shared duration field
0968:                 */
0969:                ImpreciseCutoverField(DateTimeField julianField,
0970:                        DateTimeField gregorianField,
0971:                        DurationField durationField, long cutoverMillis,
0972:                        boolean convertByWeekyear) {
0973:                    super (julianField, gregorianField, cutoverMillis,
0974:                            convertByWeekyear);
0975:                    if (durationField == null) {
0976:                        durationField = new LinkedDurationField(iDurationField,
0977:                                this );
0978:                    }
0979:                    iDurationField = durationField;
0980:                }
0981:
0982:                public long add(long instant, int value) {
0983:                    if (instant >= iCutover) {
0984:                        instant = iGregorianField.add(instant, value);
0985:                        if (instant < iCutover) {
0986:                            // Only adjust if gap fully crossed.
0987:                            if (instant + iGapDuration < iCutover) {
0988:                                instant = gregorianToJulian(instant);
0989:                            }
0990:                        }
0991:                    } else {
0992:                        instant = iJulianField.add(instant, value);
0993:                        if (instant >= iCutover) {
0994:                            // Only adjust if gap fully crossed.
0995:                            if (instant - iGapDuration >= iCutover) {
0996:                                instant = julianToGregorian(instant);
0997:                            }
0998:                        }
0999:                    }
1000:                    return instant;
1001:                }
1002:
1003:                public long add(long instant, long value) {
1004:                    if (instant >= iCutover) {
1005:                        instant = iGregorianField.add(instant, value);
1006:                        if (instant < iCutover) {
1007:                            // Only adjust if gap fully crossed.
1008:                            if (instant + iGapDuration < iCutover) {
1009:                                instant = gregorianToJulian(instant);
1010:                            }
1011:                        }
1012:                    } else {
1013:                        instant = iJulianField.add(instant, value);
1014:                        if (instant >= iCutover) {
1015:                            // Only adjust if gap fully crossed.
1016:                            if (instant - iGapDuration >= iCutover) {
1017:                                instant = julianToGregorian(instant);
1018:                            }
1019:                        }
1020:                    }
1021:                    return instant;
1022:                }
1023:
1024:                public int getDifference(long minuendInstant,
1025:                        long subtrahendInstant) {
1026:                    if (minuendInstant >= iCutover) {
1027:                        if (subtrahendInstant >= iCutover) {
1028:                            return iGregorianField.getDifference(
1029:                                    minuendInstant, subtrahendInstant);
1030:                        }
1031:                        // Remember, the add is being reversed. Since subtrahend is
1032:                        // Julian, convert minuend to Julian to match.
1033:                        minuendInstant = gregorianToJulian(minuendInstant);
1034:                        return iJulianField.getDifference(minuendInstant,
1035:                                subtrahendInstant);
1036:                    } else {
1037:                        if (subtrahendInstant < iCutover) {
1038:                            return iJulianField.getDifference(minuendInstant,
1039:                                    subtrahendInstant);
1040:                        }
1041:                        // Remember, the add is being reversed. Since subtrahend is
1042:                        // Gregorian, convert minuend to Gregorian to match.
1043:                        minuendInstant = julianToGregorian(minuendInstant);
1044:                        return iGregorianField.getDifference(minuendInstant,
1045:                                subtrahendInstant);
1046:                    }
1047:                }
1048:
1049:                public long getDifferenceAsLong(long minuendInstant,
1050:                        long subtrahendInstant) {
1051:                    if (minuendInstant >= iCutover) {
1052:                        if (subtrahendInstant >= iCutover) {
1053:                            return iGregorianField.getDifferenceAsLong(
1054:                                    minuendInstant, subtrahendInstant);
1055:                        }
1056:                        // Remember, the add is being reversed. Since subtrahend is
1057:                        // Julian, convert minuend to Julian to match.
1058:                        minuendInstant = gregorianToJulian(minuendInstant);
1059:                        return iJulianField.getDifferenceAsLong(minuendInstant,
1060:                                subtrahendInstant);
1061:                    } else {
1062:                        if (subtrahendInstant < iCutover) {
1063:                            return iJulianField.getDifferenceAsLong(
1064:                                    minuendInstant, subtrahendInstant);
1065:                        }
1066:                        // Remember, the add is being reversed. Since subtrahend is
1067:                        // Gregorian, convert minuend to Gregorian to match.
1068:                        minuendInstant = julianToGregorian(minuendInstant);
1069:                        return iGregorianField.getDifferenceAsLong(
1070:                                minuendInstant, subtrahendInstant);
1071:                    }
1072:                }
1073:
1074:                // Since the imprecise fields have durations longer than the gap
1075:                // duration, keep these methods simple. The inherited implementations
1076:                // produce incorrect results.
1077:                //
1078:                // Degenerate case: If this field is a month, and the cutover is set
1079:                // far into the future, then the gap duration may be so large as to
1080:                // reduce the number of months in a year. If the missing month(s) are
1081:                // at the beginning or end of the year, then the minimum and maximum
1082:                // values are not 1 and 12. I don't expect this case to ever occur.
1083:
1084:                public int getMinimumValue(long instant) {
1085:                    if (instant >= iCutover) {
1086:                        return iGregorianField.getMinimumValue(instant);
1087:                    } else {
1088:                        return iJulianField.getMinimumValue(instant);
1089:                    }
1090:                }
1091:
1092:                public int getMaximumValue(long instant) {
1093:                    if (instant >= iCutover) {
1094:                        return iGregorianField.getMaximumValue(instant);
1095:                    } else {
1096:                        return iJulianField.getMaximumValue(instant);
1097:                    }
1098:                }
1099:            }
1100:
1101:            //-----------------------------------------------------------------------
1102:            /**
1103:             * Links the duration back to a ImpreciseCutoverField.
1104:             */
1105:            private static class LinkedDurationField extends
1106:                    DecoratedDurationField {
1107:                private static final long serialVersionUID = 4097975388007713084L;
1108:
1109:                private final ImpreciseCutoverField iField;
1110:
1111:                LinkedDurationField(DurationField durationField,
1112:                        ImpreciseCutoverField dateTimeField) {
1113:                    super (durationField, durationField.getType());
1114:                    iField = dateTimeField;
1115:                }
1116:
1117:                public long add(long instant, int value) {
1118:                    return iField.add(instant, value);
1119:                }
1120:
1121:                public long add(long instant, long value) {
1122:                    return iField.add(instant, value);
1123:                }
1124:
1125:                public int getDifference(long minuendInstant,
1126:                        long subtrahendInstant) {
1127:                    return iField.getDifference(minuendInstant,
1128:                            subtrahendInstant);
1129:                }
1130:
1131:                public long getDifferenceAsLong(long minuendInstant,
1132:                        long subtrahendInstant) {
1133:                    return iField.getDifferenceAsLong(minuendInstant,
1134:                            subtrahendInstant);
1135:                }
1136:            }
1137:
1138:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.