001    /*
002     *  Copyright 2001-2005 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time;
017    
018    import java.util.Locale;
019    
020    /**
021     * Defines the calculation engine for date and time fields.
022     * The interface defines a set of methods that manipulate a millisecond datetime
023     * with regards to a single field, such as monthOfYear or secondOfMinute.
024     * <p>
025     * This design is extensible so, if you wish, you can extract a different field from
026     * the milliseconds. A number of standard implementations are provided to assist.
027     *
028     * @author Guy Allard
029     * @author Stephen Colebourne
030     * @author Brian S O'Neill
031     * @since 1.0
032     */
033    public abstract class DateTimeField {
034    
035        /**
036         * Get the type of the field.
037         * 
038         * @return field type
039         */
040        public abstract DateTimeFieldType getType();
041    
042        /**
043         * Get the name of the field.
044         * <p>
045         * By convention, names follow a pattern of "dddOfRrr", where "ddd" represents
046         * the (singular) duration unit field name and "Rrr" represents the (singular)
047         * duration range field name. If the range field is not applicable, then
048         * the name of the field is simply the (singular) duration field name.
049         * 
050         * @return field name
051         */
052        public abstract String getName();
053    
054        /**
055         * Returns true if this field is supported.
056         * 
057         * @return true if this field is supported
058         */
059        public abstract boolean isSupported();
060    
061        /**
062         * Returns true if the set method is lenient. If so, it accepts values that
063         * are out of bounds. For example, a lenient day of month field accepts 32
064         * for January, converting it to February 1.
065         * 
066         * @return true if this field is lenient
067         */
068        public abstract boolean isLenient();
069    
070        // Main access API
071        //------------------------------------------------------------------------
072        /**
073         * Get the value of this field from the milliseconds.
074         * 
075         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
076         * @return the value of the field, in the units of the field
077         */
078        public abstract int get(long instant);
079    
080        /**
081         * Get the human-readable, text value of this field from the milliseconds.
082         * If the specified locale is null, the default locale is used.
083         *
084         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
085         * @param locale the locale to use for selecting a text symbol, null for default
086         * @return the text value of the field
087         */
088        public abstract String getAsText(long instant, Locale locale);
089    
090        /**
091         * Get the human-readable, text value of this field from the milliseconds.
092         * 
093         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
094         * @return the text value of the field
095         */
096        public abstract String getAsText(long instant);
097    
098        /**
099         * Get the human-readable, text value of this field from a partial instant.
100         * If the specified locale is null, the default locale is used.
101         *
102         * @param partial  the partial instant to query
103         * @param fieldValue  the field value of this field, provided for performance
104         * @param locale  the locale to use for selecting a text symbol, null for default
105         * @return the text value of the field
106         */
107        public abstract String getAsText(ReadablePartial partial, int fieldValue, Locale locale);
108    
109        /**
110         * Get the human-readable, text value of this field from a partial instant.
111         * If the specified locale is null, the default locale is used.
112         *
113         * @param partial  the partial instant to query
114         * @param locale  the locale to use for selecting a text symbol, null for default
115         * @return the text value of the field
116         */
117        public abstract String getAsText(ReadablePartial partial, Locale locale);
118    
119        /**
120         * Get the human-readable, text value of this field from the field value.
121         * If the specified locale is null, the default locale is used.
122         *
123         * @param fieldValue  the numeric value to convert to text
124         * @param locale the locale to use for selecting a text symbol, null for default
125         * @return the text value of the field
126         */
127        public abstract String getAsText(int fieldValue, Locale locale);
128    
129        /**
130         * Get the human-readable, short text value of this field from the
131         * milliseconds.  If the specified locale is null, the default locale is used.
132         *
133         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
134         * @param locale the locale to use for selecting a text symbol, null for default
135         * @return the short text value of the field
136         */
137        public abstract String getAsShortText(long instant, Locale locale);
138    
139        /**
140         * Get the human-readable, short text value of this field from the
141         * milliseconds.
142         * 
143         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
144         * @return the short text value of the field
145         */
146        public abstract String getAsShortText(long instant);
147    
148        /**
149         * Get the human-readable, short text value of this field from a partial instant.
150         * If the specified locale is null, the default locale is used.
151         *
152         * @param partial  the partial instant to query
153         * @param fieldValue  the field value of this field, provided for performance
154         * @param locale  the locale to use for selecting a text symbol, null for default
155         * @return the text value of the field
156         */
157        public abstract String getAsShortText(ReadablePartial partial, int fieldValue, Locale locale);
158    
159        /**
160         * Get the human-readable, short text value of this field from a partial instant.
161         * If the specified locale is null, the default locale is used.
162         *
163         * @param partial  the partial instant to query
164         * @param locale  the locale to use for selecting a text symbol, null for default
165         * @return the text value of the field
166         */
167        public abstract String getAsShortText(ReadablePartial partial, Locale locale);
168    
169        /**
170         * Get the human-readable, short text value of this field from the field value.
171         * If the specified locale is null, the default locale is used.
172         *
173         * @param fieldValue  the numeric value to convert to text
174         * @param locale the locale to use for selecting a text symbol, null for default
175         * @return the text value of the field
176         */
177        public abstract String getAsShortText(int fieldValue, Locale locale);
178    
179        /**
180         * Adds a value (which may be negative) to the millis value,
181         * overflowing into larger fields if necessary.
182         * <p>
183         * The value will be added to this field. If the value is too large to be
184         * added solely to this field, larger fields will increase as required.
185         * Smaller fields should be unaffected, except where the result would be
186         * an invalid value for a smaller field. In this case the smaller field is
187         * adjusted to be in range.
188         * <p>
189         * For example, in the ISO chronology:<br>
190         * 2000-08-20 add six months is 2001-02-20<br>
191         * 2000-08-20 add twenty months is 2002-04-20<br>
192         * 2000-08-20 add minus nine months is 1999-11-20<br>
193         * 2001-01-31 add one month  is 2001-02-28<br>
194         * 2001-01-31 add two months is 2001-03-31<br>
195         * 
196         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to add to
197         * @param value  the value to add, in the units of the field
198         * @return the updated milliseconds
199         */
200        public abstract long add(long instant, int value);
201    
202        /**
203         * Adds a value (which may be negative) to the millis value,
204         * overflowing into larger fields if necessary.
205         * 
206         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to add to
207         * @param value  the long value to add, in the units of the field
208         * @return the updated milliseconds
209         * @throws IllegalArgumentException if value is too large
210         * @see #add(long,int)
211         */
212        public abstract long add(long instant, long value);
213    
214        /**
215         * Adds a value (which may be negative) to the partial instant,
216         * throwing an exception if the maximum size of the instant is reached.
217         * <p>
218         * The value will be added to this field, overflowing into larger fields
219         * if necessary. Smaller fields should be unaffected, except where the
220         * result would be an invalid value for a smaller field. In this case the
221         * smaller field is adjusted to be in range.
222         * <p>
223         * Partial instants only contain some fields. This may result in a maximum
224         * possible value, such as TimeOfDay being limited to 23:59:59:999. If this
225         * limit is breached by the add an exception is thrown.
226         * <p>
227         * For example, in the ISO chronology:<br>
228         * 2000-08-20 add six months is 2000-02-20<br>
229         * 2000-08-20 add twenty months is 2000-04-20<br>
230         * 2000-08-20 add minus nine months is 2000-11-20<br>
231         * 2001-01-31 add one month  is 2001-02-28<br>
232         * 2001-01-31 add two months is 2001-03-31<br>
233         * 
234         * @param instant  the partial instant
235         * @param fieldIndex  the index of this field in the instant
236         * @param values  the values of the partial instant which should be updated
237         * @param valueToAdd  the value to add, in the units of the field
238         * @return the passed in values
239         * @throws IllegalArgumentException if the value is invalid or the maximum instant is reached
240         */
241        public abstract int[] add(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd);
242    
243        /**
244         * Adds a value (which may be negative) to the partial instant,
245         * wrapping the whole partial if the maximum size of the partial is reached.
246         * <p>
247         * The value will be added to this field, overflowing into larger fields
248         * if necessary. Smaller fields should be unaffected, except where the
249         * result would be an invalid value for a smaller field. In this case the
250         * smaller field is adjusted to be in range.
251         * <p>
252         * Partial instants only contain some fields. This may result in a maximum
253         * possible value, such as TimeOfDay normally being limited to 23:59:59:999.
254         * If ths limit is reached by the addition, this method will wrap back to
255         * 00:00:00.000. In fact, you would generally only use this method for
256         * classes that have a limitation such as this.
257         * <p>
258         * For example, in the ISO chronology:<br>
259         * 10:20:30 add 20 minutes is 10:40:30<br>
260         * 10:20:30 add 45 minutes is 11:05:30<br>
261         * 10:20:30 add 16 hours is 02:20:30<br>
262         * 
263         * @param instant  the partial instant
264         * @param fieldIndex  the index of this field in the partial
265         * @param values  the values of the partial instant which should be updated
266         * @param valueToAdd  the value to add, in the units of the field
267         * @return the passed in values
268         * @throws IllegalArgumentException if the value is invalid or the maximum instant is reached
269         */
270        public abstract int[] addWrapPartial(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd);
271    
272        /**
273         * Adds a value (which may be negative) to the millis value,
274         * wrapping within this field.
275         * <p>
276         * The value will be added to this field. If the value is too large to be
277         * added solely to this field then it wraps. Larger fields are always
278         * unaffected. Smaller fields should be unaffected, except where the
279         * result would be an invalid value for a smaller field. In this case the
280         * smaller field is adjusted to be in range.
281         * <p>
282         * For example, in the ISO chronology:<br>
283         * 2000-08-20 addWrapField six months is 2000-02-20<br>
284         * 2000-08-20 addWrapField twenty months is 2000-04-20<br>
285         * 2000-08-20 addWrapField minus nine months is 2000-11-20<br>
286         * 2001-01-31 addWrapField one month  is 2001-02-28<br>
287         * 2001-01-31 addWrapField two months is 2001-03-31<br>
288         * 
289         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to add to
290         * @param value  the value to add, in the units of the field
291         * @return the updated milliseconds
292         */
293        public abstract long addWrapField(long instant, int value) ;
294    
295        /**
296         * Adds a value (which may be negative) to the partial instant,
297         * wrapping within this field.
298         * <p>
299         * The value will be added to this field. If the value is too large to be
300         * added solely to this field then it wraps. Larger fields are always
301         * unaffected. Smaller fields should be unaffected, except where the
302         * result would be an invalid value for a smaller field. In this case the
303         * smaller field is adjusted to be in range.
304         * <p>
305         * For example, in the ISO chronology:<br>
306         * 2000-08-20 addWrapField six months is 2000-02-20<br>
307         * 2000-08-20 addWrapField twenty months is 2000-04-20<br>
308         * 2000-08-20 addWrapField minus nine months is 2000-11-20<br>
309         * 2001-01-31 addWrapField one month  is 2001-02-28<br>
310         * 2001-01-31 addWrapField two months is 2001-03-31<br>
311         * 
312         * @param instant  the partial instant
313         * @param fieldIndex  the index of this field in the instant
314         * @param values  the values of the partial instant which should be updated
315         * @param valueToAdd  the value to add, in the units of the field
316         * @return the passed in values
317         * @throws IllegalArgumentException if the value is invalid
318         */
319        public abstract int[] addWrapField(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd);
320    
321        /**
322         * Computes the difference between two instants, as measured in the units
323         * of this field. Any fractional units are dropped from the result. Calling
324         * getDifference reverses the effect of calling add. In the following code:
325         *
326         * <pre>
327         * long instant = ...
328         * int v = ...
329         * int age = getDifference(add(instant, v), instant);
330         * </pre>
331         *
332         * The value 'age' is the same as the value 'v'.
333         *
334         * @param minuendInstant the milliseconds from 1970-01-01T00:00:00Z to
335         * subtract from
336         * @param subtrahendInstant the milliseconds from 1970-01-01T00:00:00Z to
337         * subtract off the minuend
338         * @return the difference in the units of this field
339         */
340        public abstract int getDifference(long minuendInstant, long subtrahendInstant);
341    
342        /**
343         * Computes the difference between two instants, as measured in the units
344         * of this field. Any fractional units are dropped from the result. Calling
345         * getDifference reverses the effect of calling add. In the following code:
346         *
347         * <pre>
348         * long instant = ...
349         * long v = ...
350         * long age = getDifferenceAsLong(add(instant, v), instant);
351         * </pre>
352         *
353         * The value 'age' is the same as the value 'v'.
354         *
355         * @param minuendInstant the milliseconds from 1970-01-01T00:00:00Z to
356         * subtract from
357         * @param subtrahendInstant the milliseconds from 1970-01-01T00:00:00Z to
358         * subtract off the minuend
359         * @return the difference in the units of this field
360         */
361        public abstract long getDifferenceAsLong(long minuendInstant, long subtrahendInstant);
362    
363        /**
364         * Sets a value in the milliseconds supplied.
365         * <p>
366         * The value of this field will be set.
367         * If the value is invalid, an exception if thrown.
368         * <p>
369         * If setting this field would make other fields invalid, then those fields
370         * may be changed. For example if the current date is the 31st January, and
371         * the month is set to February, the day would be invalid. Instead, the day
372         * would be changed to the closest value - the 28th/29th February as appropriate.
373         * 
374         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to set in
375         * @param value  the value to set, in the units of the field
376         * @return the updated milliseconds
377         * @throws IllegalArgumentException if the value is invalid
378         */
379        public abstract long set(long instant, int value);
380    
381        /**
382         * Sets a value using the specified partial instant.
383         * <p>
384         * The value of this field (specified by the index) will be set.
385         * If the value is invalid, an exception if thrown.
386         * <p>
387         * If setting this field would make other fields invalid, then those fields
388         * may be changed. For example if the current date is the 31st January, and
389         * the month is set to February, the day would be invalid. Instead, the day
390         * would be changed to the closest value - the 28th/29th February as appropriate.
391         * 
392         * @param instant  the partial instant
393         * @param fieldIndex  the index of this field in the instant
394         * @param values  the values of the partial instant which should be updated
395         * @param newValue  the value to set, in the units of the field
396         * @return the passed in values
397         * @throws IllegalArgumentException if the value is invalid
398         */
399        public abstract int[] set(ReadablePartial instant, int fieldIndex, int[] values, int newValue);
400    
401        /**
402         * Sets a value in the milliseconds supplied from a human-readable, text value.
403         * If the specified locale is null, the default locale is used.
404         * <p>
405         * If setting this field would make other fields invalid, then those fields
406         * may be changed. For example if the current date is the 31st January, and
407         * the month is set to February, the day would be invalid. Instead, the day
408         * would be changed to the closest value - the 28th/29th February as appropriate.
409         *
410         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to set in
411         * @param text  the text value to set
412         * @param locale the locale to use for selecting a text symbol, null for default
413         * @return the updated milliseconds
414         * @throws IllegalArgumentException if the text value is invalid
415         */
416        public abstract long set(long instant, String text, Locale locale);
417    
418        /**
419         * Sets a value in the milliseconds supplied from a human-readable, text value.
420         * <p>
421         * If setting this field would make other fields invalid, then those fields
422         * may be changed. For example if the current date is the 31st January, and
423         * the month is set to February, the day would be invalid. Instead, the day
424         * would be changed to the closest value - the 28th/29th February as appropriate.
425         * 
426         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to set in
427         * @param text  the text value to set
428         * @return the updated milliseconds
429         * @throws IllegalArgumentException if the text value is invalid
430         */
431        public abstract long set(long instant, String text);
432    
433        /**
434         * Sets a value in the milliseconds supplied from a human-readable, text value.
435         * If the specified locale is null, the default locale is used.
436         * <p>
437         * If setting this field would make other fields invalid, then those fields
438         * may be changed. For example if the current date is the 31st January, and
439         * the month is set to February, the day would be invalid. Instead, the day
440         * would be changed to the closest value - the 28th/29th February as appropriate.
441         *
442         * @param instant  the partial instant
443         * @param fieldIndex  the index of this field in the instant
444         * @param values  the values of the partial instant which should be updated
445         * @param text  the text value to set
446         * @param locale the locale to use for selecting a text symbol, null for default
447         * @return the passed in values
448         * @throws IllegalArgumentException if the text value is invalid
449         */
450        public abstract int[] set(ReadablePartial instant, int fieldIndex, int[] values, String text, Locale locale);
451    
452        // Extra information API
453        //------------------------------------------------------------------------
454        /**
455         * Returns the duration per unit value of this field. For example, if this
456         * field represents "hour of day", then the duration is an hour.
457         *
458         * @return the duration of this field, or UnsupportedDurationField if field
459         * has no duration
460         */
461        public abstract DurationField getDurationField();
462    
463        /**
464         * Returns the range duration of this field. For example, if this field
465         * represents "hour of day", then the range duration is a day.
466         *
467         * @return the range duration of this field, or null if field has no range
468         */
469        public abstract DurationField getRangeDurationField();
470    
471        /**
472         * Returns whether this field is 'leap' for the specified instant.
473         * <p>
474         * For example, a leap year would return true, a non leap year would return
475         * false.
476         * 
477         * @param instant  the instant to check for leap status
478         * @return true if the field is 'leap'
479         */
480        public abstract boolean isLeap(long instant);
481    
482        /**
483         * Gets the amount by which this field is 'leap' for the specified instant.
484         * <p>
485         * For example, a leap year would return one, a non leap year would return
486         * zero.
487         * 
488         * @param instant  the instant to check for leap status
489         * @return the amount, in units of the leap duration field, that the field is leap
490         */
491        public abstract int getLeapAmount(long instant);
492    
493        /**
494         * If this field were to leap, then it would be in units described by the
495         * returned duration. If this field doesn't ever leap, null is returned.
496         * 
497         * @return the leap duration field if field can be leap, null if it can't
498         */
499        public abstract DurationField getLeapDurationField();
500    
501        /**
502         * Get the minimum allowable value for this field.
503         * 
504         * @return the minimum valid value for this field, in the units of the
505         * field
506         */
507        public abstract int getMinimumValue();
508    
509        /**
510         * Get the minimum value for this field evaluated at the specified time.
511         * 
512         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
513         * @return the minimum value for this field, in the units of the field
514         */
515        public abstract int getMinimumValue(long instant);
516    
517        /**
518         * Get the minimum value for this field evaluated at the specified time.
519         * 
520         * @param instant  the partial instant to query
521         * @return the minimum value for this field, in the units of the field
522         */
523        public abstract int getMinimumValue(ReadablePartial instant);
524    
525        /**
526         * Get the minimum value for this field using the partial instant and
527         * the specified values.
528         * 
529         * @param instant  the partial instant to query
530         * @param values  the values to use
531         * @return the minimum value for this field, in the units of the field
532         */
533        public abstract int getMinimumValue(ReadablePartial instant, int[] values);
534    
535        /**
536         * Get the maximum allowable value for this field.
537         * 
538         * @return the maximum valid value for this field, in the units of the
539         * field
540         */
541        public abstract int getMaximumValue();
542    
543        /**
544         * Get the maximum value for this field evaluated at the specified time.
545         * 
546         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to query
547         * @return the maximum value for this field, in the units of the field
548         */
549        public abstract int getMaximumValue(long instant);
550    
551        /**
552         * Get the maximum value for this field evaluated at the specified time.
553         * 
554         * @param instant  the partial instant to query
555         * @return the maximum value for this field, in the units of the field
556         */
557        public abstract int getMaximumValue(ReadablePartial instant);
558    
559        /**
560         * Get the maximum value for this field using the partial instant and
561         * the specified values.
562         * 
563         * @param instant  the partial instant to query
564         * @param values  the values to use
565         * @return the maximum value for this field, in the units of the field
566         */
567        public abstract int getMaximumValue(ReadablePartial instant, int[] values);
568    
569        /**
570         * Get the maximum text value for this field.
571         * 
572         * @param locale  the locale to use for selecting a text symbol
573         * @return the maximum text length
574         */
575        public abstract int getMaximumTextLength(Locale locale);
576    
577        /**
578         * Get the maximum short text value for this field.
579         * 
580         * @param locale  the locale to use for selecting a text symbol
581         * @return the maximum short text length
582         */
583        public abstract int getMaximumShortTextLength(Locale locale);
584    
585        // Calculation API
586        //------------------------------------------------------------------------
587        /**
588         * Round to the lowest whole unit of this field. After rounding, the value
589         * of this field and all fields of a higher magnitude are retained. The
590         * fractional millis that cannot be expressed in whole increments of this
591         * field are set to minimum.
592         * <p>
593         * For example, a datetime of 2002-11-02T23:34:56.789, rounded to the
594         * lowest whole hour is 2002-11-02T23:00:00.000.
595         *
596         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to round
597         * @return rounded milliseconds
598         */
599        public abstract long roundFloor(long instant);
600    
601        /**
602         * Round to the highest whole unit of this field. The value of this field
603         * and all fields of a higher magnitude may be incremented in order to
604         * achieve this result. The fractional millis that cannot be expressed in
605         * whole increments of this field are set to minimum.
606         * <p>
607         * For example, a datetime of 2002-11-02T23:34:56.789, rounded to the
608         * highest whole hour is 2002-11-03T00:00:00.000.
609         *
610         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to round
611         * @return rounded milliseconds
612         */
613        public abstract long roundCeiling(long instant);
614    
615        /**
616         * Round to the nearest whole unit of this field. If the given millisecond
617         * value is closer to the floor or is exactly halfway, this function
618         * behaves like roundFloor. If the millisecond value is closer to the
619         * ceiling, this function behaves like roundCeiling.
620         *
621         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to round
622         * @return rounded milliseconds
623         */
624        public abstract long roundHalfFloor(long instant);
625    
626        /**
627         * Round to the nearest whole unit of this field. If the given millisecond
628         * value is closer to the floor, this function behaves like roundFloor. If
629         * the millisecond value is closer to the ceiling or is exactly halfway,
630         * this function behaves like roundCeiling.
631         *
632         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to round
633         * @return rounded milliseconds
634         */
635        public abstract long roundHalfCeiling(long instant);
636    
637        /**
638         * Round to the nearest whole unit of this field. If the given millisecond
639         * value is closer to the floor, this function behaves like roundFloor. If
640         * the millisecond value is closer to the ceiling, this function behaves
641         * like roundCeiling.
642         * <p>
643         * If the millisecond value is exactly halfway between the floor and
644         * ceiling, the ceiling is chosen over the floor only if it makes this
645         * field's value even.
646         *
647         * @param instant  the milliseconds from 1970-01-01T00:00:00Z to round
648         * @return rounded milliseconds
649         */
650        public abstract long roundHalfEven(long instant);
651    
652        /**
653         * Returns the fractional duration milliseconds of this field. In other
654         * words, calling remainder returns the duration that roundFloor would
655         * subtract.
656         * <p>
657         * For example, on a datetime of 2002-11-02T23:34:56.789, the remainder by
658         * hour is 34 minutes and 56.789 seconds.
659         *
660         * @param instant the milliseconds from 1970-01-01T00:00:00Z to get the
661         * remainder
662         * @return remainder duration, in milliseconds
663         */
664        public abstract long remainder(long instant);
665    
666        /**
667         * Get a suitable debug string.
668         * 
669         * @return debug string
670         */
671        public abstract String toString();
672        
673    }