test/java/time/tck/java/time/chrono/CopticDate.java

Print this page




  51  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  52  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  53  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  54  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  55  */
  56 package tck.java.time.chrono;
  57 
  58 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
  59 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
  60 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
  61 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
  62 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
  63 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  64 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
  65 
  66 import java.io.Serializable;
  67 
  68 import java.time.DateTimeException;
  69 import java.time.LocalDate;
  70 import java.time.Period;

  71 import java.time.chrono.ChronoLocalDate;
  72 import java.time.temporal.ChronoField;
  73 import java.time.temporal.ChronoUnit;
  74 import java.time.temporal.Temporal;
  75 import java.time.temporal.TemporalField;
  76 import java.time.temporal.TemporalUnit;
  77 import java.time.temporal.ValueRange;
  78 import java.time.Year;
  79 
  80 /**
  81  * A date in the Coptic calendar system.
  82  * <p>
  83  * This implements {@code ChronoLocalDate} for the {@link CopticChronology Coptic calendar}.
  84  *
  85  * <h4>Implementation notes</h4>
  86  * This class is immutable and thread-safe.
  87  */
  88 public final class CopticDate
  89         implements ChronoLocalDate<CopticDate>, Serializable {
  90 
  91     /**
  92      * Serialization version.
  93      */
  94     private static final long serialVersionUID = -7920528871688876868L;
  95     /**
  96      * The difference between the Coptic and Coptic epoch day count.
  97      */
  98     private static final int EPOCH_DAY_DIFFERENCE = 574971 + 40587;


 184             default:
 185                 return 30;
 186         }
 187     }
 188 
 189     @Override
 190     public ValueRange range(TemporalField field) {
 191         if (field instanceof ChronoField) {
 192             if (isSupported(field)) {
 193                 ChronoField f = (ChronoField) field;
 194                 switch (f) {
 195                     case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
 196                     case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
 197                     case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, month == 13 ? 1 : 5);
 198                     case YEAR:
 199                     case YEAR_OF_ERA: return (prolepticYear <= 0 ?
 200                             ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));  // TODO
 201                 }
 202                 return getChronology().range(f);
 203             }
 204             throw new DateTimeException("Unsupported field: " + field.getName());
 205         }
 206         return field.rangeRefinedBy(this);
 207     }
 208 
 209     @Override
 210     public long getLong(TemporalField field) {
 211         if (field instanceof ChronoField) {
 212             switch ((ChronoField) field) {
 213                 case DAY_OF_WEEK: return Math.floorMod(toEpochDay() + 3, 7) + 1;
 214                 case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
 215                 case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((get(ChronoField.DAY_OF_YEAR) - 1) % 7) + 1;
 216                 case DAY_OF_MONTH: return day;
 217                 case DAY_OF_YEAR: return (month - 1) * 30 + day;
 218                 case EPOCH_DAY: return toEpochDay();
 219                 case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
 220                 case ALIGNED_WEEK_OF_YEAR: return ((get(ChronoField.DAY_OF_YEAR) - 1) / 7) + 1;
 221                 case MONTH_OF_YEAR: return month;
 222                 case YEAR_OF_ERA: return (prolepticYear >= 1 ? prolepticYear : 1 - prolepticYear);
 223                 case YEAR: return prolepticYear;
 224                 case ERA: return (prolepticYear >= 1 ? 1 : 0);
 225             }
 226             throw new DateTimeException("Unsupported field: " + field.getName());
 227         }
 228         return field.getFrom(this);
 229     }
 230 
 231     @Override
 232     public CopticDate with(TemporalField field, long newValue) {
 233         if (field instanceof ChronoField) {
 234             ChronoField f = (ChronoField) field;
 235             f.checkValidValue(newValue);        // TODO: validate value
 236             int nvalue = (int) newValue;
 237             switch (f) {
 238                 case DAY_OF_WEEK: return plusDays(newValue - get(ChronoField.DAY_OF_WEEK));
 239                 case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));
 240                 case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));
 241                 case DAY_OF_MONTH: return resolvePreviousValid(prolepticYear, month, nvalue);
 242                 case DAY_OF_YEAR: return resolvePreviousValid(prolepticYear, ((nvalue - 1) / 30) + 1, ((nvalue - 1) % 30) + 1);
 243                 case EPOCH_DAY: return ofEpochDay(nvalue);
 244                 case ALIGNED_WEEK_OF_MONTH: return plusDays((newValue - getLong(ALIGNED_WEEK_OF_MONTH)) * 7);
 245                 case ALIGNED_WEEK_OF_YEAR: return plusDays((newValue - getLong(ALIGNED_WEEK_OF_YEAR)) * 7);
 246                 case MONTH_OF_YEAR: return resolvePreviousValid(prolepticYear, nvalue, day);
 247                 case YEAR_OF_ERA: return resolvePreviousValid(prolepticYear >= 1 ? nvalue : 1 - nvalue, month, day);
 248                 case YEAR: return resolvePreviousValid(nvalue, month, day);
 249                 case ERA: return resolvePreviousValid(1 - prolepticYear, month, day);
 250             }
 251             throw new DateTimeException("Unsupported field: " + field.getName());
 252         }
 253         return field.adjustInto(this, newValue);
 254     }
 255 
 256     //-----------------------------------------------------------------------
 257     @Override
 258     public CopticDate plus(long amountToAdd, TemporalUnit unit) {
 259         if (unit instanceof ChronoUnit) {
 260             ChronoUnit f = (ChronoUnit) unit;
 261             switch (f) {
 262                 case DAYS: return plusDays(amountToAdd);
 263                 case WEEKS: return plusDays(Math.multiplyExact(amountToAdd, 7));
 264                 case MONTHS: return plusMonths(amountToAdd);
 265                 case YEARS: return plusYears(amountToAdd);
 266                 case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));
 267                 case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));
 268                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
 269             }
 270             throw new DateTimeException(unit.getName() + " not valid for CopticDate");
 271         }
 272         return unit.addTo(this, amountToAdd);
 273     }
 274 
 275     //-----------------------------------------------------------------------
 276     private CopticDate plusYears(long years) {
 277         return plusMonths(Math.multiplyExact(years, 13));
 278     }
 279 
 280     private CopticDate plusMonths(long months) {
 281         if (months == 0) {
 282             return this;
 283         }
 284         long curEm = prolepticYear * 13L + (month - 1);
 285         long calcEm = Math.addExact(curEm, months);
 286         int newYear = Math.toIntExact(Math.floorDiv(calcEm, 13));
 287         int newMonth = (int)Math.floorMod(calcEm, 13) + 1;
 288         return resolvePreviousValid(newYear, newMonth, day);
 289     }
 290 




  51  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  52  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  53  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  54  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  55  */
  56 package tck.java.time.chrono;
  57 
  58 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
  59 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
  60 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
  61 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
  62 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
  63 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  64 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
  65 
  66 import java.io.Serializable;
  67 
  68 import java.time.DateTimeException;
  69 import java.time.LocalDate;
  70 import java.time.Period;
  71 import java.time.Year;
  72 import java.time.chrono.ChronoLocalDate;
  73 import java.time.temporal.ChronoField;
  74 import java.time.temporal.ChronoUnit;
  75 import java.time.temporal.Temporal;
  76 import java.time.temporal.TemporalField;
  77 import java.time.temporal.TemporalUnit;
  78 import java.time.temporal.ValueRange;
  79 import java.time.temporal.UnsupportedTemporalTypeException;
  80 
  81 /**
  82  * A date in the Coptic calendar system.
  83  * <p>
  84  * This implements {@code ChronoLocalDate} for the {@link CopticChronology Coptic calendar}.
  85  *
  86  * <h4>Implementation notes</h4>
  87  * This class is immutable and thread-safe.
  88  */
  89 public final class CopticDate
  90         implements ChronoLocalDate<CopticDate>, Serializable {
  91 
  92     /**
  93      * Serialization version.
  94      */
  95     private static final long serialVersionUID = -7920528871688876868L;
  96     /**
  97      * The difference between the Coptic and Coptic epoch day count.
  98      */
  99     private static final int EPOCH_DAY_DIFFERENCE = 574971 + 40587;


 185             default:
 186                 return 30;
 187         }
 188     }
 189 
 190     @Override
 191     public ValueRange range(TemporalField field) {
 192         if (field instanceof ChronoField) {
 193             if (isSupported(field)) {
 194                 ChronoField f = (ChronoField) field;
 195                 switch (f) {
 196                     case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
 197                     case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
 198                     case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, month == 13 ? 1 : 5);
 199                     case YEAR:
 200                     case YEAR_OF_ERA: return (prolepticYear <= 0 ?
 201                             ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));  // TODO
 202                 }
 203                 return getChronology().range(f);
 204             }
 205             throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
 206         }
 207         return field.rangeRefinedBy(this);
 208     }
 209 
 210     @Override
 211     public long getLong(TemporalField field) {
 212         if (field instanceof ChronoField) {
 213             switch ((ChronoField) field) {
 214                 case DAY_OF_WEEK: return Math.floorMod(toEpochDay() + 3, 7) + 1;
 215                 case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
 216                 case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((get(ChronoField.DAY_OF_YEAR) - 1) % 7) + 1;
 217                 case DAY_OF_MONTH: return day;
 218                 case DAY_OF_YEAR: return (month - 1) * 30 + day;
 219                 case EPOCH_DAY: return toEpochDay();
 220                 case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
 221                 case ALIGNED_WEEK_OF_YEAR: return ((get(ChronoField.DAY_OF_YEAR) - 1) / 7) + 1;
 222                 case MONTH_OF_YEAR: return month;
 223                 case YEAR_OF_ERA: return (prolepticYear >= 1 ? prolepticYear : 1 - prolepticYear);
 224                 case YEAR: return prolepticYear;
 225                 case ERA: return (prolepticYear >= 1 ? 1 : 0);
 226             }
 227             throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
 228         }
 229         return field.getFrom(this);
 230     }
 231 
 232     @Override
 233     public CopticDate with(TemporalField field, long newValue) {
 234         if (field instanceof ChronoField) {
 235             ChronoField f = (ChronoField) field;
 236             f.checkValidValue(newValue);        // TODO: validate value
 237             int nvalue = (int) newValue;
 238             switch (f) {
 239                 case DAY_OF_WEEK: return plusDays(newValue - get(ChronoField.DAY_OF_WEEK));
 240                 case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));
 241                 case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));
 242                 case DAY_OF_MONTH: return resolvePreviousValid(prolepticYear, month, nvalue);
 243                 case DAY_OF_YEAR: return resolvePreviousValid(prolepticYear, ((nvalue - 1) / 30) + 1, ((nvalue - 1) % 30) + 1);
 244                 case EPOCH_DAY: return ofEpochDay(nvalue);
 245                 case ALIGNED_WEEK_OF_MONTH: return plusDays((newValue - getLong(ALIGNED_WEEK_OF_MONTH)) * 7);
 246                 case ALIGNED_WEEK_OF_YEAR: return plusDays((newValue - getLong(ALIGNED_WEEK_OF_YEAR)) * 7);
 247                 case MONTH_OF_YEAR: return resolvePreviousValid(prolepticYear, nvalue, day);
 248                 case YEAR_OF_ERA: return resolvePreviousValid(prolepticYear >= 1 ? nvalue : 1 - nvalue, month, day);
 249                 case YEAR: return resolvePreviousValid(nvalue, month, day);
 250                 case ERA: return resolvePreviousValid(1 - prolepticYear, month, day);
 251             }
 252             throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
 253         }
 254         return field.adjustInto(this, newValue);
 255     }
 256 
 257     //-----------------------------------------------------------------------
 258     @Override
 259     public CopticDate plus(long amountToAdd, TemporalUnit unit) {
 260         if (unit instanceof ChronoUnit) {
 261             ChronoUnit f = (ChronoUnit) unit;
 262             switch (f) {
 263                 case DAYS: return plusDays(amountToAdd);
 264                 case WEEKS: return plusDays(Math.multiplyExact(amountToAdd, 7));
 265                 case MONTHS: return plusMonths(amountToAdd);
 266                 case YEARS: return plusYears(amountToAdd);
 267                 case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));
 268                 case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));
 269                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
 270             }
 271             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
 272         }
 273         return unit.addTo(this, amountToAdd);
 274     }
 275 
 276     //-----------------------------------------------------------------------
 277     private CopticDate plusYears(long years) {
 278         return plusMonths(Math.multiplyExact(years, 13));
 279     }
 280 
 281     private CopticDate plusMonths(long months) {
 282         if (months == 0) {
 283             return this;
 284         }
 285         long curEm = prolepticYear * 13L + (month - 1);
 286         long calcEm = Math.addExact(curEm, months);
 287         int newYear = Math.toIntExact(Math.floorDiv(calcEm, 13));
 288         int newMonth = (int)Math.floorMod(calcEm, 13) + 1;
 289         return resolvePreviousValid(newYear, newMonth, day);
 290     }
 291