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


0001:        /*
0002:         *  Copyright 2001-2006 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;
0017:
0018:        import java.io.Serializable;
0019:        import java.util.ArrayList;
0020:        import java.util.Arrays;
0021:        import java.util.List;
0022:        import java.util.Locale;
0023:
0024:        import org.joda.time.base.AbstractPartial;
0025:        import org.joda.time.field.AbstractPartialFieldProperty;
0026:        import org.joda.time.field.FieldUtils;
0027:        import org.joda.time.format.DateTimeFormat;
0028:        import org.joda.time.format.DateTimeFormatter;
0029:        import org.joda.time.format.ISODateTimeFormat;
0030:
0031:        /**
0032:         * Partial is an immutable partial datetime supporting any set of datetime fields.
0033:         * <p>
0034:         * A Partial instance can be used to hold any combination of fields.
0035:         * The instance does not contain a time zone, so any datetime is local.
0036:         * <p>
0037:         * A Partial can be matched against an instant using {@link #isMatch(ReadableInstant)}.
0038:         * This method compares each field on this partial with those of the instant
0039:         * and determines if the partial matches the instant.
0040:         * Given this definition, an empty Partial instance represents any datetime
0041:         * and always matches.
0042:         * <p>
0043:         * Calculations on Partial are performed using a {@link Chronology}.
0044:         * This chronology is set to be in the UTC time zone for all calculations.
0045:         * <p>
0046:         * Each individual field can be queried in two ways:
0047:         * <ul>
0048:         * <li><code>get(DateTimeFieldType.monthOfYear())</code>
0049:         * <li><code>property(DateTimeFieldType.monthOfYear()).get()</code>
0050:         * </ul>
0051:         * The second technique also provides access to other useful methods on the
0052:         * field:
0053:         * <ul>
0054:         * <li>numeric value - <code>monthOfYear().get()</code>
0055:         * <li>text value - <code>monthOfYear().getAsText()</code>
0056:         * <li>short text value - <code>monthOfYear().getAsShortText()</code>
0057:         * <li>maximum/minimum values - <code>monthOfYear().getMaximumValue()</code>
0058:         * <li>add/subtract - <code>monthOfYear().addToCopy()</code>
0059:         * <li>set - <code>monthOfYear().setCopy()</code>
0060:         * </ul>
0061:         * <p>
0062:         * Partial is thread-safe and immutable, provided that the Chronology is as well.
0063:         * All standard Chronology classes supplied are thread-safe and immutable.
0064:         *
0065:         * @author Stephen Colebourne
0066:         * @since 1.1
0067:         */
0068:        public final class Partial extends AbstractPartial implements 
0069:                ReadablePartial, Serializable {
0070:
0071:            /** Serialization version */
0072:            private static final long serialVersionUID = 12324121189002L;
0073:
0074:            /** The chronology in use. */
0075:            private final Chronology iChronology;
0076:            /** The set of field types. */
0077:            private final DateTimeFieldType[] iTypes;
0078:            /** The values of each field in this partial. */
0079:            private final int[] iValues;
0080:            /** The formatter to use, [0] may miss some fields, [1] doesn't miss any fields. */
0081:            private transient DateTimeFormatter[] iFormatter;
0082:
0083:            // Constructors
0084:            //-----------------------------------------------------------------------
0085:            /**
0086:             * Constructs a Partial with no fields or values, which can be considered
0087:             * to represent any date.
0088:             * <p>
0089:             * This is most useful when constructing partials, for example:
0090:             * <pre>
0091:             * Partial p = new Partial()
0092:             *     .with(DateTimeFieldType.dayOfWeek(), 5)
0093:             *     .with(DateTimeFieldType.hourOfDay(), 12)
0094:             *     .with(DateTimeFieldType.minuteOfHour(), 20);
0095:             * </pre>
0096:             * Note that, although this is a clean way to write code, it is fairly
0097:             * inefficient internally.
0098:             * <p>
0099:             * The constructor uses the default ISO chronology.
0100:             */
0101:            public Partial() {
0102:                this ((Chronology) null);
0103:            }
0104:
0105:            /**
0106:             * Constructs a Partial with no fields or values, which can be considered
0107:             * to represent any date.
0108:             * <p>
0109:             * This is most useful when constructing partials, for example:
0110:             * <pre>
0111:             * Partial p = new Partial(chrono)
0112:             *     .with(DateTimeFieldType.dayOfWeek(), 5)
0113:             *     .with(DateTimeFieldType.hourOfDay(), 12)
0114:             *     .with(DateTimeFieldType.minuteOfHour(), 20);
0115:             * </pre>
0116:             * Note that, although this is a clean way to write code, it is fairly
0117:             * inefficient internally.
0118:             *
0119:             * @param chrono  the chronology, null means ISO
0120:             */
0121:            public Partial(Chronology chrono) {
0122:                super ();
0123:                iChronology = DateTimeUtils.getChronology(chrono).withUTC();
0124:                iTypes = new DateTimeFieldType[0];
0125:                iValues = new int[0];
0126:            }
0127:
0128:            /**
0129:             * Constructs a Partial with the specified field and value.
0130:             * <p>
0131:             * The constructor uses the default ISO chronology.
0132:             * 
0133:             * @param type  the single type to create the partial from, not null
0134:             * @param value  the value to store
0135:             * @throws IllegalArgumentException if the type or value is invalid
0136:             */
0137:            public Partial(DateTimeFieldType type, int value) {
0138:                this (type, value, null);
0139:            }
0140:
0141:            /**
0142:             * Constructs a Partial with the specified field and value.
0143:             * <p>
0144:             * The constructor uses the specified chronology.
0145:             * 
0146:             * @param type  the single type to create the partial from, not null
0147:             * @param value  the value to store
0148:             * @param chronology  the chronology, null means ISO
0149:             * @throws IllegalArgumentException if the type or value is invalid
0150:             */
0151:            public Partial(DateTimeFieldType type, int value,
0152:                    Chronology chronology) {
0153:                super ();
0154:                chronology = DateTimeUtils.getChronology(chronology).withUTC();
0155:                iChronology = chronology;
0156:                if (type == null) {
0157:                    throw new IllegalArgumentException(
0158:                            "The field type must not be null");
0159:                }
0160:                iTypes = new DateTimeFieldType[] { type };
0161:                iValues = new int[] { value };
0162:                chronology.validate(this , iValues);
0163:            }
0164:
0165:            /**
0166:             * Constructs a Partial with the specified fields and values.
0167:             * The fields must be specified in the order largest to smallest.
0168:             * <p>
0169:             * The constructor uses the specified chronology.
0170:             * 
0171:             * @param types  the types to create the partial from, not null
0172:             * @param values  the values to store, not null
0173:             * @throws IllegalArgumentException if the types or values are invalid
0174:             */
0175:            public Partial(DateTimeFieldType[] types, int[] values) {
0176:                this (types, values, null);
0177:            }
0178:
0179:            /**
0180:             * Constructs a Partial with the specified fields and values.
0181:             * The fields must be specified in the order largest to smallest.
0182:             * <p>
0183:             * The constructor uses the specified chronology.
0184:             * 
0185:             * @param types  the types to create the partial from, not null
0186:             * @param values  the values to store, not null
0187:             * @param chronology  the chronology, null means ISO
0188:             * @throws IllegalArgumentException if the types or values are invalid
0189:             */
0190:            public Partial(DateTimeFieldType[] types, int[] values,
0191:                    Chronology chronology) {
0192:                super ();
0193:                chronology = DateTimeUtils.getChronology(chronology).withUTC();
0194:                iChronology = chronology;
0195:                if (types == null) {
0196:                    throw new IllegalArgumentException(
0197:                            "Types array must not be null");
0198:                }
0199:                if (values == null) {
0200:                    throw new IllegalArgumentException(
0201:                            "Values array must not be null");
0202:                }
0203:                if (values.length != types.length) {
0204:                    throw new IllegalArgumentException(
0205:                            "Values array must be the same length as the types array");
0206:                }
0207:                if (types.length == 0) {
0208:                    iTypes = types;
0209:                    iValues = values;
0210:                    return;
0211:                }
0212:                for (int i = 0; i < types.length; i++) {
0213:                    if (types[i] == null) {
0214:                        throw new IllegalArgumentException(
0215:                                "Types array must not contain null: index " + i);
0216:                    }
0217:                }
0218:                DurationField lastUnitField = null;
0219:                for (int i = 0; i < types.length; i++) {
0220:                    DateTimeFieldType loopType = types[i];
0221:                    DurationField loopUnitField = loopType.getDurationType()
0222:                            .getField(iChronology);
0223:                    if (i > 0) {
0224:                        int compare = lastUnitField.compareTo(loopUnitField);
0225:                        if (compare < 0
0226:                                || (compare != 0 && loopUnitField.isSupported() == false)) {
0227:                            throw new IllegalArgumentException(
0228:                                    "Types array must be in order largest-smallest: "
0229:                                            + types[i - 1].getName() + " < "
0230:                                            + loopType.getName());
0231:                        } else if (compare == 0) {
0232:                            if (types[i - 1].getRangeDurationType() == null) {
0233:                                if (loopType.getRangeDurationType() == null) {
0234:                                    throw new IllegalArgumentException(
0235:                                            "Types array must not contain duplicate: "
0236:                                                    + loopType.getName());
0237:                                }
0238:                            } else {
0239:                                if (loopType.getRangeDurationType() == null) {
0240:                                    throw new IllegalArgumentException(
0241:                                            "Types array must be in order largest-smallest: "
0242:                                                    + types[i - 1].getName()
0243:                                                    + " < "
0244:                                                    + loopType.getName());
0245:                                }
0246:                                DurationField lastRangeField = types[i - 1]
0247:                                        .getRangeDurationType().getField(
0248:                                                iChronology);
0249:                                DurationField loopRangeField = loopType
0250:                                        .getRangeDurationType().getField(
0251:                                                iChronology);
0252:                                if (lastRangeField.compareTo(loopRangeField) < 0) {
0253:                                    throw new IllegalArgumentException(
0254:                                            "Types array must be in order largest-smallest: "
0255:                                                    + types[i - 1].getName()
0256:                                                    + " < "
0257:                                                    + loopType.getName());
0258:                                }
0259:                                if (lastRangeField.compareTo(loopRangeField) == 0) {
0260:                                    throw new IllegalArgumentException(
0261:                                            "Types array must not contain duplicate: "
0262:                                                    + loopType.getName());
0263:                                }
0264:                            }
0265:                        }
0266:                    }
0267:                    lastUnitField = loopUnitField;
0268:                }
0269:
0270:                iTypes = (DateTimeFieldType[]) types.clone();
0271:                chronology.validate(this , values);
0272:                iValues = (int[]) values.clone();
0273:            }
0274:
0275:            /**
0276:             * Constructs a Partial by copying all the fields and types from
0277:             * another partial.
0278:             * <p>
0279:             * This is most useful when copying from a YearMonthDay or TimeOfDay.
0280:             */
0281:            public Partial(ReadablePartial partial) {
0282:                super ();
0283:                if (partial == null) {
0284:                    throw new IllegalArgumentException(
0285:                            "The partial must not be null");
0286:                }
0287:                iChronology = DateTimeUtils.getChronology(
0288:                        partial.getChronology()).withUTC();
0289:                iTypes = new DateTimeFieldType[partial.size()];
0290:                iValues = new int[partial.size()];
0291:                for (int i = 0; i < partial.size(); i++) {
0292:                    iTypes[i] = partial.getFieldType(i);
0293:                    iValues[i] = partial.getValue(i);
0294:                }
0295:            }
0296:
0297:            /**
0298:             * Constructs a Partial with the specified values.
0299:             * This constructor assigns and performs no validation.
0300:             * 
0301:             * @param partial  the partial to copy
0302:             * @param values  the values to store
0303:             * @throws IllegalArgumentException if the types or values are invalid
0304:             */
0305:            Partial(Partial partial, int[] values) {
0306:                super ();
0307:                iChronology = partial.iChronology;
0308:                iTypes = partial.iTypes;
0309:                iValues = values;
0310:            }
0311:
0312:            /**
0313:             * Constructs a Partial with the specified chronology, fields and values.
0314:             * This constructor assigns and performs no validation.
0315:             * 
0316:             * @param chronology  the chronology
0317:             * @param types  the types to create the partial from
0318:             * @param values  the values to store
0319:             * @throws IllegalArgumentException if the types or values are invalid
0320:             */
0321:            Partial(Chronology chronology, DateTimeFieldType[] types,
0322:                    int[] values) {
0323:                super ();
0324:                iChronology = chronology;
0325:                iTypes = types;
0326:                iValues = values;
0327:            }
0328:
0329:            //-----------------------------------------------------------------------
0330:            /**
0331:             * Gets the number of fields in this partial.
0332:             * 
0333:             * @return the field count
0334:             */
0335:            public int size() {
0336:                return iTypes.length;
0337:            }
0338:
0339:            /**
0340:             * Gets the chronology of the partial which is never null.
0341:             * <p>
0342:             * The {@link Chronology} is the calculation engine behind the partial and
0343:             * provides conversion and validation of the fields in a particular calendar system.
0344:             * 
0345:             * @return the chronology, never null
0346:             */
0347:            public Chronology getChronology() {
0348:                return iChronology;
0349:            }
0350:
0351:            /**
0352:             * Gets the field for a specific index in the chronology specified.
0353:             * 
0354:             * @param index  the index to retrieve
0355:             * @param chrono  the chronology to use
0356:             * @return the field
0357:             * @throws IndexOutOfBoundsException if the index is invalid
0358:             */
0359:            protected DateTimeField getField(int index, Chronology chrono) {
0360:                return iTypes[index].getField(chrono);
0361:            }
0362:
0363:            /**
0364:             * Gets the field type at the specified index.
0365:             *
0366:             * @param index  the index to retrieve
0367:             * @return the field at the specified index
0368:             * @throws IndexOutOfBoundsException if the index is invalid
0369:             */
0370:            public DateTimeFieldType getFieldType(int index) {
0371:                return iTypes[index];
0372:            }
0373:
0374:            /**
0375:             * Gets an array of the field type of each of the fields that
0376:             * this partial supports.
0377:             * <p>
0378:             * The fields are returned largest to smallest.
0379:             *
0380:             * @return the array of field types (cloned), largest to smallest
0381:             */
0382:            public DateTimeFieldType[] getFieldTypes() {
0383:                return (DateTimeFieldType[]) iTypes.clone();
0384:            }
0385:
0386:            //-----------------------------------------------------------------------
0387:            /**
0388:             * Gets the value of the field at the specifed index.
0389:             * 
0390:             * @param index  the index
0391:             * @return the value
0392:             * @throws IndexOutOfBoundsException if the index is invalid
0393:             */
0394:            public int getValue(int index) {
0395:                return iValues[index];
0396:            }
0397:
0398:            /**
0399:             * Gets an array of the value of each of the fields that
0400:             * this partial supports.
0401:             * <p>
0402:             * The fields are returned largest to smallest.
0403:             * Each value corresponds to the same array index as <code>getFieldTypes()</code>
0404:             *
0405:             * @return the current values of each field (cloned), largest to smallest
0406:             */
0407:            public int[] getValues() {
0408:                return (int[]) iValues.clone();
0409:            }
0410:
0411:            //-----------------------------------------------------------------------
0412:            /**
0413:             * Creates a new Partial instance with the specified chronology.
0414:             * This instance is immutable and unaffected by this method call.
0415:             * <p>
0416:             * This method retains the values of the fields, thus the result will
0417:             * typically refer to a different instant.
0418:             * <p>
0419:             * The time zone of the specified chronology is ignored, as Partial
0420:             * operates without a time zone.
0421:             *
0422:             * @param newChronology  the new chronology, null means ISO
0423:             * @return a copy of this datetime with a different chronology
0424:             * @throws IllegalArgumentException if the values are invalid for the new chronology
0425:             */
0426:            public Partial withChronologyRetainFields(Chronology newChronology) {
0427:                newChronology = DateTimeUtils.getChronology(newChronology);
0428:                newChronology = newChronology.withUTC();
0429:                if (newChronology == getChronology()) {
0430:                    return this ;
0431:                } else {
0432:                    Partial newPartial = new Partial(newChronology, iTypes,
0433:                            iValues);
0434:                    newChronology.validate(newPartial, iValues);
0435:                    return newPartial;
0436:                }
0437:            }
0438:
0439:            //-----------------------------------------------------------------------
0440:            /**
0441:             * Gets a copy of this date with the specified field set to a new value.
0442:             * <p>
0443:             * If this partial did not previously support the field, the new one will.
0444:             * Contrast this behaviour with {@link #withField(DateTimeFieldType, int)}.
0445:             * <p>
0446:             * For example, if the field type is <code>dayOfMonth</code> then the day
0447:             * would be changed/added in the returned instance.
0448:             *
0449:             * @param fieldType  the field type to set, not null
0450:             * @param value  the value to set
0451:             * @return a copy of this instance with the field set
0452:             * @throws IllegalArgumentException if the value is null or invalid
0453:             */
0454:            public Partial with(DateTimeFieldType fieldType, int value) {
0455:                if (fieldType == null) {
0456:                    throw new IllegalArgumentException(
0457:                            "The field type must not be null");
0458:                }
0459:                int index = indexOf(fieldType);
0460:                if (index == -1) {
0461:                    DateTimeFieldType[] newTypes = new DateTimeFieldType[iTypes.length + 1];
0462:                    int[] newValues = new int[newTypes.length];
0463:
0464:                    // find correct insertion point to keep largest-smallest order
0465:                    int i = 0;
0466:                    DurationField unitField = fieldType.getDurationType()
0467:                            .getField(iChronology);
0468:                    if (unitField.isSupported()) {
0469:                        for (; i < iTypes.length; i++) {
0470:                            DateTimeFieldType loopType = iTypes[i];
0471:                            DurationField loopUnitField = loopType
0472:                                    .getDurationType().getField(iChronology);
0473:                            if (loopUnitField.isSupported()) {
0474:                                int compare = unitField
0475:                                        .compareTo(loopUnitField);
0476:                                if (compare > 0) {
0477:                                    break;
0478:                                } else if (compare == 0) {
0479:                                    DurationField rangeField = fieldType
0480:                                            .getRangeDurationType().getField(
0481:                                                    iChronology);
0482:                                    DurationField loopRangeField = loopType
0483:                                            .getRangeDurationType().getField(
0484:                                                    iChronology);
0485:                                    if (rangeField.compareTo(loopRangeField) > 0) {
0486:                                        break;
0487:                                    }
0488:                                }
0489:                            }
0490:                        }
0491:                    }
0492:                    System.arraycopy(iTypes, 0, newTypes, 0, i);
0493:                    System.arraycopy(iValues, 0, newValues, 0, i);
0494:                    newTypes[i] = fieldType;
0495:                    newValues[i] = value;
0496:                    System.arraycopy(iTypes, i, newTypes, i + 1,
0497:                            newTypes.length - i - 1);
0498:                    System.arraycopy(iValues, i, newValues, i + 1,
0499:                            newValues.length - i - 1);
0500:
0501:                    Partial newPartial = new Partial(iChronology, newTypes,
0502:                            newValues);
0503:                    iChronology.validate(newPartial, newValues);
0504:                    return newPartial;
0505:                }
0506:                if (value == getValue(index)) {
0507:                    return this ;
0508:                }
0509:                int[] newValues = getValues();
0510:                newValues = getField(index).set(this , index, newValues, value);
0511:                return new Partial(this , newValues);
0512:            }
0513:
0514:            /**
0515:             * Gets a copy of this date with the specified field removed.
0516:             * <p>
0517:             * If this partial did not previously support the field, no error occurs.
0518:             *
0519:             * @param fieldType  the field type to remove, may be null
0520:             * @return a copy of this instance with the field removed
0521:             */
0522:            public Partial without(DateTimeFieldType fieldType) {
0523:                int index = indexOf(fieldType);
0524:                if (index != -1) {
0525:                    DateTimeFieldType[] newTypes = new DateTimeFieldType[size() - 1];
0526:                    int[] newValues = new int[size() - 1];
0527:                    System.arraycopy(iTypes, 0, newTypes, 0, index);
0528:                    System.arraycopy(iTypes, index + 1, newTypes, index,
0529:                            newTypes.length - index);
0530:                    System.arraycopy(iValues, 0, newValues, 0, index);
0531:                    System.arraycopy(iValues, index + 1, newValues, index,
0532:                            newValues.length - index);
0533:                    Partial newPartial = new Partial(iChronology, newTypes,
0534:                            newValues);
0535:                    iChronology.validate(newPartial, newValues);
0536:                    return newPartial;
0537:                }
0538:                return this ;
0539:            }
0540:
0541:            //-----------------------------------------------------------------------
0542:            /**
0543:             * Gets a copy of this Partial with the specified field set to a new value.
0544:             * <p>
0545:             * If this partial does not support the field, an exception is thrown.
0546:             * Contrast this behaviour with {@link #with(DateTimeFieldType, int)}.
0547:             * <p>
0548:             * For example, if the field type is <code>dayOfMonth</code> then the day
0549:             * would be changed in the returned instance if supported.
0550:             *
0551:             * @param fieldType  the field type to set, not null
0552:             * @param value  the value to set
0553:             * @return a copy of this instance with the field set
0554:             * @throws IllegalArgumentException if the value is null or invalid
0555:             */
0556:            public Partial withField(DateTimeFieldType fieldType, int value) {
0557:                int index = indexOfSupported(fieldType);
0558:                if (value == getValue(index)) {
0559:                    return this ;
0560:                }
0561:                int[] newValues = getValues();
0562:                newValues = getField(index).set(this , index, newValues, value);
0563:                return new Partial(this , newValues);
0564:            }
0565:
0566:            /**
0567:             * Gets a copy of this Partial with the value of the specified field increased.
0568:             * If this partial does not support the field, an exception is thrown.
0569:             * <p>
0570:             * If the addition is zero, then <code>this</code> is returned.
0571:             * The addition will overflow into larger fields (eg. minute to hour).
0572:             * However, it will not wrap around if the top maximum is reached.
0573:             *
0574:             * @param fieldType  the field type to add to, not null
0575:             * @param amount  the amount to add
0576:             * @return a copy of this instance with the field updated
0577:             * @throws IllegalArgumentException if the value is null or invalid
0578:             * @throws ArithmeticException if the new datetime exceeds the capacity
0579:             */
0580:            public Partial withFieldAdded(DurationFieldType fieldType,
0581:                    int amount) {
0582:                int index = indexOfSupported(fieldType);
0583:                if (amount == 0) {
0584:                    return this ;
0585:                }
0586:                int[] newValues = getValues();
0587:                newValues = getField(index).add(this , index, newValues, amount);
0588:                return new Partial(this , newValues);
0589:            }
0590:
0591:            /**
0592:             * Gets a copy of this Partial with the value of the specified field increased.
0593:             * If this partial does not support the field, an exception is thrown.
0594:             * <p>
0595:             * If the addition is zero, then <code>this</code> is returned.
0596:             * The addition will overflow into larger fields (eg. minute to hour).
0597:             * If the maximum is reached, the addition will wra.
0598:             *
0599:             * @param fieldType  the field type to add to, not null
0600:             * @param amount  the amount to add
0601:             * @return a copy of this instance with the field updated
0602:             * @throws IllegalArgumentException if the value is null or invalid
0603:             * @throws ArithmeticException if the new datetime exceeds the capacity
0604:             */
0605:            public Partial withFieldAddWrapped(DurationFieldType fieldType,
0606:                    int amount) {
0607:                int index = indexOfSupported(fieldType);
0608:                if (amount == 0) {
0609:                    return this ;
0610:                }
0611:                int[] newValues = getValues();
0612:                newValues = getField(index).addWrapPartial(this , index,
0613:                        newValues, amount);
0614:                return new Partial(this , newValues);
0615:            }
0616:
0617:            /**
0618:             * Gets a copy of this Partial with the specified period added.
0619:             * <p>
0620:             * If the addition is zero, then <code>this</code> is returned.
0621:             * Fields in the period that aren't present in the partial are ignored.
0622:             * <p>
0623:             * This method is typically used to add multiple copies of complex
0624:             * period instances. Adding one field is best achieved using the method
0625:             * {@link #withFieldAdded(DurationFieldType, int)}.
0626:             * 
0627:             * @param period  the period to add to this one, null means zero
0628:             * @param scalar  the amount of times to add, such as -1 to subtract once
0629:             * @return a copy of this instance with the period added
0630:             * @throws ArithmeticException if the new datetime exceeds the capacity
0631:             */
0632:            public Partial withPeriodAdded(ReadablePeriod period, int scalar) {
0633:                if (period == null || scalar == 0) {
0634:                    return this ;
0635:                }
0636:                int[] newValues = getValues();
0637:                for (int i = 0; i < period.size(); i++) {
0638:                    DurationFieldType fieldType = period.getFieldType(i);
0639:                    int index = indexOf(fieldType);
0640:                    if (index >= 0) {
0641:                        newValues = getField(index).add(
0642:                                this ,
0643:                                index,
0644:                                newValues,
0645:                                FieldUtils.safeMultiply(period.getValue(i),
0646:                                        scalar));
0647:                    }
0648:                }
0649:                return new Partial(this , newValues);
0650:            }
0651:
0652:            /**
0653:             * Gets a copy of this instance with the specified period added.
0654:             * <p>
0655:             * If the amount is zero or null, then <code>this</code> is returned.
0656:             *
0657:             * @param period  the duration to add to this one, null means zero
0658:             * @return a copy of this instance with the period added
0659:             * @throws ArithmeticException if the new datetime exceeds the capacity of a long
0660:             */
0661:            public Partial plus(ReadablePeriod period) {
0662:                return withPeriodAdded(period, 1);
0663:            }
0664:
0665:            /**
0666:             * Gets a copy of this instance with the specified period take away.
0667:             * <p>
0668:             * If the amount is zero or null, then <code>this</code> is returned.
0669:             *
0670:             * @param period  the period to reduce this instant by
0671:             * @return a copy of this instance with the period taken away
0672:             * @throws ArithmeticException if the new datetime exceeds the capacity of a long
0673:             */
0674:            public Partial minus(ReadablePeriod period) {
0675:                return withPeriodAdded(period, -1);
0676:            }
0677:
0678:            //-----------------------------------------------------------------------
0679:            /**
0680:             * Gets the property object for the specified type, which contains
0681:             * many useful methods for getting and manipulating the partial.
0682:             * <p>
0683:             * See also {@link ReadablePartial#get(DateTimeFieldType)}.
0684:             *
0685:             * @param type  the field type to get the property for, not null
0686:             * @return the property object
0687:             * @throws IllegalArgumentException if the field is null or unsupported
0688:             */
0689:            public Property property(DateTimeFieldType type) {
0690:                return new Property(this , indexOfSupported(type));
0691:            }
0692:
0693:            //-----------------------------------------------------------------------
0694:            /**
0695:             * Does this partial match the specified instant.
0696:             * <p>
0697:             * A match occurs when all the fields of this partial are the same as the
0698:             * corresponding fields on the specified instant.
0699:             *
0700:             * @param instant  an instant to check against, null means now in default zone
0701:             * @return true if this partial matches the specified instant
0702:             */
0703:            public boolean isMatch(ReadableInstant instant) {
0704:                long millis = DateTimeUtils.getInstantMillis(instant);
0705:                Chronology chrono = DateTimeUtils.getInstantChronology(instant);
0706:                for (int i = 0; i < iTypes.length; i++) {
0707:                    int value = iTypes[i].getField(chrono).get(millis);
0708:                    if (value != iValues[i]) {
0709:                        return false;
0710:                    }
0711:                }
0712:                return true;
0713:            }
0714:
0715:            /**
0716:             * Does this partial match the specified partial.
0717:             * <p>
0718:             * A match occurs when all the fields of this partial are the same as the
0719:             * corresponding fields on the specified partial.
0720:             *
0721:             * @param partial  a partial to check against, must not be null
0722:             * @return true if this partial matches the specified partial
0723:             * @throws IllegalArgumentException if the partial is null
0724:             * @throws IllegalArgumentException if the fields of the two partials do not match
0725:             * @since 1.5
0726:             */
0727:            public boolean isMatch(ReadablePartial partial) {
0728:                if (partial == null) {
0729:                    throw new IllegalArgumentException(
0730:                            "The partial must not be null");
0731:                }
0732:                for (int i = 0; i < iTypes.length; i++) {
0733:                    int value = partial.get(iTypes[i]);
0734:                    if (value != iValues[i]) {
0735:                        return false;
0736:                    }
0737:                }
0738:                return true;
0739:            }
0740:
0741:            //-----------------------------------------------------------------------
0742:            /**
0743:             * Gets a formatter suitable for the fields in this partial.
0744:             * <p>
0745:             * If there is no appropriate ISO format, null is returned.
0746:             * This method may return a formatter that does not display all the
0747:             * fields of the partial. This might occur when you have overlapping
0748:             * fields, such as dayOfWeek and dayOfMonth.
0749:             *
0750:             * @return a formatter suitable for the fields in this partial, null
0751:             *  if none is suitable
0752:             */
0753:            public DateTimeFormatter getFormatter() {
0754:                DateTimeFormatter[] f = iFormatter;
0755:                if (f == null) {
0756:                    if (size() == 0) {
0757:                        return null;
0758:                    }
0759:                    f = new DateTimeFormatter[2];
0760:                    try {
0761:                        List list = new ArrayList(Arrays.asList(iTypes));
0762:                        f[0] = ISODateTimeFormat.forFields(list, true, false);
0763:                        if (list.size() == 0) {
0764:                            f[1] = f[0];
0765:                        }
0766:                    } catch (IllegalArgumentException ex) {
0767:                        // ignore
0768:                    }
0769:                    iFormatter = f;
0770:                }
0771:                return f[0];
0772:            }
0773:
0774:            //-----------------------------------------------------------------------
0775:            /**
0776:             * Output the date in an appropriate ISO8601 format.
0777:             * <p>
0778:             * This method will output the partial in one of two ways.
0779:             * If {@link #getFormatter()}
0780:             * <p>
0781:             * If there is no appropriate ISO format a dump of the fields is output
0782:             * via {@link #toStringList()}.
0783:             * 
0784:             * @return ISO8601 formatted string
0785:             */
0786:            public String toString() {
0787:                DateTimeFormatter[] f = iFormatter;
0788:                if (f == null) {
0789:                    getFormatter();
0790:                    f = iFormatter;
0791:                    if (f == null) {
0792:                        return toStringList();
0793:                    }
0794:                }
0795:                DateTimeFormatter f1 = f[1];
0796:                if (f1 == null) {
0797:                    return toStringList();
0798:                }
0799:                return f1.print(this );
0800:            }
0801:
0802:            /**
0803:             * Gets a string version of the partial that lists all the fields.
0804:             * <p>
0805:             * This method exists to provide a better debugging toString than
0806:             * the standard toString. This method lists all the fields and their
0807:             * values in a style similar to the collections framework.
0808:             *
0809:             * @return a toString format that lists all the fields
0810:             */
0811:            public String toStringList() {
0812:                int size = size();
0813:                StringBuffer buf = new StringBuffer(20 * size);
0814:                buf.append('[');
0815:                for (int i = 0; i < size; i++) {
0816:                    if (i > 0) {
0817:                        buf.append(',').append(' ');
0818:                    }
0819:                    buf.append(iTypes[i].getName());
0820:                    buf.append('=');
0821:                    buf.append(iValues[i]);
0822:                }
0823:                buf.append(']');
0824:                return buf.toString();
0825:            }
0826:
0827:            /**
0828:             * Output the date using the specified format pattern.
0829:             * Unsupported fields will appear as special unicode characters.
0830:             *
0831:             * @param pattern  the pattern specification, null means use <code>toString</code>
0832:             * @see org.joda.time.format.DateTimeFormat
0833:             */
0834:            public String toString(String pattern) {
0835:                if (pattern == null) {
0836:                    return toString();
0837:                }
0838:                return DateTimeFormat.forPattern(pattern).print(this );
0839:            }
0840:
0841:            /**
0842:             * Output the date using the specified format pattern.
0843:             * Unsupported fields will appear as special unicode characters.
0844:             *
0845:             * @param pattern  the pattern specification, null means use <code>toString</code>
0846:             * @param locale  Locale to use, null means default
0847:             * @see org.joda.time.format.DateTimeFormat
0848:             */
0849:            public String toString(String pattern, Locale locale) {
0850:                if (pattern == null) {
0851:                    return toString();
0852:                }
0853:                return DateTimeFormat.forPattern(pattern).withLocale(locale)
0854:                        .print(this );
0855:            }
0856:
0857:            //-----------------------------------------------------------------------
0858:            /**
0859:             * The property class for <code>Partial</code>.
0860:             * <p>
0861:             * This class binds a <code>Partial</code> to a <code>DateTimeField</code>.
0862:             * 
0863:             * @author Stephen Colebourne
0864:             * @since 1.1
0865:             */
0866:            public static class Property extends AbstractPartialFieldProperty
0867:                    implements  Serializable {
0868:
0869:                /** Serialization version */
0870:                private static final long serialVersionUID = 53278362873888L;
0871:
0872:                /** The partial */
0873:                private final Partial iPartial;
0874:                /** The field index */
0875:                private final int iFieldIndex;
0876:
0877:                /**
0878:                 * Constructs a property.
0879:                 * 
0880:                 * @param partial  the partial instance
0881:                 * @param fieldIndex  the index in the partial
0882:                 */
0883:                Property(Partial partial, int fieldIndex) {
0884:                    super ();
0885:                    iPartial = partial;
0886:                    iFieldIndex = fieldIndex;
0887:                }
0888:
0889:                /**
0890:                 * Gets the field that this property uses.
0891:                 * 
0892:                 * @return the field
0893:                 */
0894:                public DateTimeField getField() {
0895:                    return iPartial.getField(iFieldIndex);
0896:                }
0897:
0898:                /**
0899:                 * Gets the partial that this property belongs to.
0900:                 * 
0901:                 * @return the partial
0902:                 */
0903:                protected ReadablePartial getReadablePartial() {
0904:                    return iPartial;
0905:                }
0906:
0907:                /**
0908:                 * Gets the partial that this property belongs to.
0909:                 * 
0910:                 * @return the partial
0911:                 */
0912:                public Partial getPartial() {
0913:                    return iPartial;
0914:                }
0915:
0916:                /**
0917:                 * Gets the value of this field.
0918:                 * 
0919:                 * @return the field value
0920:                 */
0921:                public int get() {
0922:                    return iPartial.getValue(iFieldIndex);
0923:                }
0924:
0925:                //-----------------------------------------------------------------------
0926:                /**
0927:                 * Adds to the value of this field in a copy of this Partial.
0928:                 * <p>
0929:                 * The value will be added to this field. If the value is too large to be
0930:                 * added solely to this field then it will affect larger fields.
0931:                 * Smaller fields are unaffected.
0932:                 * <p>
0933:                 * If the result would be too large, beyond the maximum year, then an
0934:                 * IllegalArgumentException is thrown.
0935:                 * <p>
0936:                 * The Partial attached to this property is unchanged by this call.
0937:                 * Instead, a new instance is returned.
0938:                 * 
0939:                 * @param valueToAdd  the value to add to the field in the copy
0940:                 * @return a copy of the Partial with the field value changed
0941:                 * @throws IllegalArgumentException if the value isn't valid
0942:                 */
0943:                public Partial addToCopy(int valueToAdd) {
0944:                    int[] newValues = iPartial.getValues();
0945:                    newValues = getField().add(iPartial, iFieldIndex,
0946:                            newValues, valueToAdd);
0947:                    return new Partial(iPartial, newValues);
0948:                }
0949:
0950:                /**
0951:                 * Adds to the value of this field in a copy of this Partial wrapping
0952:                 * within this field if the maximum value is reached.
0953:                 * <p>
0954:                 * The value will be added to this field. If the value is too large to be
0955:                 * added solely to this field then it wraps within this field.
0956:                 * Other fields are unaffected.
0957:                 * <p>
0958:                 * For example,
0959:                 * <code>2004-12-20</code> addWrapField one month returns <code>2004-01-20</code>.
0960:                 * <p>
0961:                 * The Partial attached to this property is unchanged by this call.
0962:                 * Instead, a new instance is returned.
0963:                 * 
0964:                 * @param valueToAdd  the value to add to the field in the copy
0965:                 * @return a copy of the Partial with the field value changed
0966:                 * @throws IllegalArgumentException if the value isn't valid
0967:                 */
0968:                public Partial addWrapFieldToCopy(int valueToAdd) {
0969:                    int[] newValues = iPartial.getValues();
0970:                    newValues = getField().addWrapField(iPartial, iFieldIndex,
0971:                            newValues, valueToAdd);
0972:                    return new Partial(iPartial, newValues);
0973:                }
0974:
0975:                //-----------------------------------------------------------------------
0976:                /**
0977:                 * Sets this field in a copy of the Partial.
0978:                 * <p>
0979:                 * The Partial attached to this property is unchanged by this call.
0980:                 * Instead, a new instance is returned.
0981:                 * 
0982:                 * @param value  the value to set the field in the copy to
0983:                 * @return a copy of the Partial with the field value changed
0984:                 * @throws IllegalArgumentException if the value isn't valid
0985:                 */
0986:                public Partial setCopy(int value) {
0987:                    int[] newValues = iPartial.getValues();
0988:                    newValues = getField().set(iPartial, iFieldIndex,
0989:                            newValues, value);
0990:                    return new Partial(iPartial, newValues);
0991:                }
0992:
0993:                /**
0994:                 * Sets this field in a copy of the Partial to a parsed text value.
0995:                 * <p>
0996:                 * The Partial attached to this property is unchanged by this call.
0997:                 * Instead, a new instance is returned.
0998:                 * 
0999:                 * @param text  the text value to set
1000:                 * @param locale  optional locale to use for selecting a text symbol
1001:                 * @return a copy of the Partial with the field value changed
1002:                 * @throws IllegalArgumentException if the text value isn't valid
1003:                 */
1004:                public Partial setCopy(String text, Locale locale) {
1005:                    int[] newValues = iPartial.getValues();
1006:                    newValues = getField().set(iPartial, iFieldIndex,
1007:                            newValues, text, locale);
1008:                    return new Partial(iPartial, newValues);
1009:                }
1010:
1011:                /**
1012:                 * Sets this field in a copy of the Partial to a parsed text value.
1013:                 * <p>
1014:                 * The Partial attached to this property is unchanged by this call.
1015:                 * Instead, a new instance is returned.
1016:                 * 
1017:                 * @param text  the text value to set
1018:                 * @return a copy of the Partial with the field value changed
1019:                 * @throws IllegalArgumentException if the text value isn't valid
1020:                 */
1021:                public Partial setCopy(String text) {
1022:                    return setCopy(text, null);
1023:                }
1024:
1025:                //-----------------------------------------------------------------------
1026:                /**
1027:                 * Returns a new Partial with this field set to the maximum value
1028:                 * for this field.
1029:                 * <p>
1030:                 * The Partial attached to this property is unchanged by this call.
1031:                 *
1032:                 * @return a copy of the Partial with this field set to its maximum
1033:                 * @since 1.2
1034:                 */
1035:                public Partial withMaximumValue() {
1036:                    return setCopy(getMaximumValue());
1037:                }
1038:
1039:                /**
1040:                 * Returns a new Partial with this field set to the minimum value
1041:                 * for this field.
1042:                 * <p>
1043:                 * The Partial attached to this property is unchanged by this call.
1044:                 *
1045:                 * @return a copy of the Partial with this field set to its minimum
1046:                 * @since 1.2
1047:                 */
1048:                public Partial withMinimumValue() {
1049:                    return setCopy(getMinimumValue());
1050:                }
1051:            }
1052:
1053:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.