diff --git a/src/java.base/share/classes/sun/util/calendar/AbstractCalendar.java b/src/java.base/share/classes/sun/util/calendar/AbstractCalendar.java index 50c8be6e314..f2582b80e47 100644 --- a/src/java.base/share/classes/sun/util/calendar/AbstractCalendar.java +++ b/src/java.base/share/classes/sun/util/calendar/AbstractCalendar.java @@ -44,7 +44,8 @@ import java.util.TimeZone; * @since 1.5 */ -public abstract class AbstractCalendar extends CalendarSystem { +public sealed abstract class AbstractCalendar extends CalendarSystem + permits BaseCalendar { // The constants assume no leap seconds support. static final int SECOND_IN_MILLIS = 1000; @@ -60,6 +61,7 @@ public abstract class AbstractCalendar extends CalendarSystem { protected AbstractCalendar() { } + @Override public Era getEra(String eraName) { if (eras != null) { for (Era era : eras) { @@ -71,6 +73,7 @@ public abstract class AbstractCalendar extends CalendarSystem { return null; } + @Override public Era[] getEras() { Era[] e = null; if (eras != null) { @@ -84,19 +87,23 @@ public abstract class AbstractCalendar extends CalendarSystem { this.eras = eras; } + @Override public CalendarDate getCalendarDate() { return getCalendarDate(System.currentTimeMillis(), newCalendarDate()); } + @Override public CalendarDate getCalendarDate(long millis) { return getCalendarDate(millis, newCalendarDate()); } + @Override public CalendarDate getCalendarDate(long millis, TimeZone zone) { CalendarDate date = newCalendarDate(zone); return getCalendarDate(millis, date); } + @Override public CalendarDate getCalendarDate(long millis, CalendarDate date) { int ms = 0; // time of day int zoneOffset = 0; @@ -156,6 +163,7 @@ public abstract class AbstractCalendar extends CalendarSystem { return date; } + @Override public long getTime(CalendarDate date) { long gd = getFixedDate(date); long ms = (gd - EPOCH_OFFSET) * DAY_IN_MILLIS + getTimeOfDay(date); @@ -232,6 +240,7 @@ public abstract class AbstractCalendar extends CalendarSystem { protected abstract boolean isLeapYear(CalendarDate date); + @Override public CalendarDate getNthDayOfWeek(int nth, int dayOfWeek, CalendarDate date) { CalendarDate ndate = (CalendarDate) date.clone(); normalize(ndate); diff --git a/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java b/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java index efe1b85fc21..9749ab31afd 100644 --- a/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java +++ b/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java @@ -36,7 +36,8 @@ import java.util.TimeZone; * @since 1.5 */ -public abstract class BaseCalendar extends AbstractCalendar { +public sealed abstract class BaseCalendar extends AbstractCalendar + permits Gregorian, JulianCalendar, LocalGregorianCalendar { public static final int JANUARY = 1; public static final int FEBRUARY = 2; @@ -140,7 +141,8 @@ public abstract class BaseCalendar extends AbstractCalendar { 744365, // 2039 }; - public abstract static class Date extends CalendarDate { + public sealed abstract static class Date extends CalendarDate + permits Gregorian.Date, ImmutableGregorianDate, JulianCalendar.Date, LocalGregorianCalendar.Date { protected Date() { super(); } @@ -188,6 +190,7 @@ public abstract class BaseCalendar extends AbstractCalendar { } } + @Override public boolean validate(CalendarDate date) { Date bdate = (Date) date; if (bdate.isNormalized()) { @@ -214,6 +217,7 @@ public abstract class BaseCalendar extends AbstractCalendar { return true; } + @Override public boolean normalize(CalendarDate date) { if (date.isNormalized()) { return true; @@ -303,6 +307,7 @@ public abstract class BaseCalendar extends AbstractCalendar { * @throws ClassCastException if the specified date is not a * {@link BaseCalendar.Date} */ + @Override public int getYearLength(CalendarDate date) { return isLeapYear(((Date)date).getNormalizedYear()) ? 366 : 365; } @@ -318,6 +323,7 @@ public abstract class BaseCalendar extends AbstractCalendar { // 12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1 = { -30, 0, 31, 59+1, 90+1,120+1,151+1,181+1,212+1,243+1, 273+1, 304+1, 334+1}; + @Override public int getMonthLength(CalendarDate date) { Date gdate = (Date) date; int month = gdate.getMonth(); @@ -349,6 +355,7 @@ public abstract class BaseCalendar extends AbstractCalendar { } // protected + @Override public long getFixedDate(CalendarDate date) { if (!date.isNormalized()) { normalizeMonth(date); @@ -415,6 +422,7 @@ public abstract class BaseCalendar extends AbstractCalendar { * {@code CalendarDate}. */ // should be 'protected' + @Override public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) { Date gdate = (Date) date; @@ -473,7 +481,7 @@ public abstract class BaseCalendar extends AbstractCalendar { return getDayOfWeekFromFixedDate(fixedDate); } - public static final int getDayOfWeekFromFixedDate(long fixedDate) { + public static int getDayOfWeekFromFixedDate(long fixedDate) { // The fixed day 1 (January 1, 1 Gregorian) is Monday. if (fixedDate >= 0) { return (int)(fixedDate % 7) + SUNDAY; @@ -525,6 +533,7 @@ public abstract class BaseCalendar extends AbstractCalendar { * false otherwise. * @see CalendarUtils#isGregorianLeapYear */ + @Override protected boolean isLeapYear(CalendarDate date) { return isLeapYear(((Date)date).getNormalizedYear()); } diff --git a/src/java.base/share/classes/sun/util/calendar/CalendarDate.java b/src/java.base/share/classes/sun/util/calendar/CalendarDate.java index 528baa9e317..7485a9fb37a 100644 --- a/src/java.base/share/classes/sun/util/calendar/CalendarDate.java +++ b/src/java.base/share/classes/sun/util/calendar/CalendarDate.java @@ -59,7 +59,8 @@ import java.util.TimeZone; * @author Masayoshi Okutsu * @since 1.5 */ -public abstract class CalendarDate implements Cloneable { +public sealed abstract class CalendarDate implements Cloneable + permits BaseCalendar.Date { public static final int FIELD_UNDEFINED = Integer.MIN_VALUE; public static final long TIME_UNDEFINED = Long.MIN_VALUE; @@ -340,6 +341,7 @@ public abstract class CalendarDate implements Cloneable { && zoneOffset == that.zoneOffset); } + @Override public int hashCode() { // a pseudo (local standard) time stamp value in milliseconds // from the Epoch, assuming Gregorian calendar fields. @@ -362,6 +364,7 @@ public abstract class CalendarDate implements Cloneable { * * @return a copy of this CalendarDate */ + @Override public Object clone() { try { return super.clone(); @@ -380,6 +383,7 @@ public abstract class CalendarDate implements Cloneable { * * @see java.text.SimpleDateFormat */ + @Override public String toString() { StringBuilder sb = new StringBuilder(); CalendarUtils.sprintf0d(sb, year, 4).append('-'); diff --git a/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java b/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java index 885150fc0a4..ea4f76c5bf0 100644 --- a/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java +++ b/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java @@ -65,7 +65,7 @@ import java.util.concurrent.ConcurrentMap; * @since 1.5 */ -public abstract class CalendarSystem { +public sealed abstract class CalendarSystem permits AbstractCalendar { /////////////////////// Calendar Factory Methods ///////////////////////// diff --git a/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java b/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java index 5723ebcbee0..60c2decc48b 100644 --- a/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java +++ b/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java @@ -25,7 +25,10 @@ package sun.util.calendar; -public class CalendarUtils { +public final class CalendarUtils { + + // Utility class should not be instantiated + private CalendarUtils() {} /** * Returns whether the specified year is a leap year in the Gregorian @@ -36,9 +39,9 @@ public class CalendarUtils { * calendar system. * @see CalendarDate#isLeapYear */ - public static final boolean isGregorianLeapYear(int gregorianYear) { - return (((gregorianYear % 4) == 0) - && (((gregorianYear % 100) != 0) || ((gregorianYear % 400) == 0))); + public static boolean isGregorianLeapYear(int gregorianYear) { + return (((gregorianYear % 4) == 0) && (((gregorianYear % 100) != 0) + || ((gregorianYear % 400) == 0))); } /** @@ -51,7 +54,7 @@ public class CalendarUtils { * calendar system. * @see CalendarDate#isLeapYear */ - public static final boolean isJulianLeapYear(int normalizedJulianYear) { + public static boolean isJulianLeapYear(int normalizedJulianYear) { return (normalizedJulianYear % 4) == 0; } @@ -64,7 +67,7 @@ public class CalendarUtils { * @param d a divisor that must be greater than 0 * @return the floor of the quotient */ - public static final long floorDivide(long n, long d) { + public static long floorDivide(long n, long d) { return ((n >= 0) ? (n / d) : (((n + 1L) / d) - 1L)); } @@ -78,7 +81,7 @@ public class CalendarUtils { * @param d a divisor that must be greater than 0 * @return the floor of the quotient */ - public static final int floorDivide(int n, int d) { + public static int floorDivide(int n, int d) { return ((n >= 0) ? (n / d) : (((n + 1) / d) - 1)); } @@ -96,7 +99,7 @@ public class CalendarUtils { * mod(n, d) is returned. * @return the floor of the quotient. */ - public static final int floorDivide(int n, int d, int[] r) { + public static int floorDivide(int n, int d, int[] r) { if (n >= 0) { r[0] = n % d; return n / d; @@ -106,20 +109,20 @@ public class CalendarUtils { return q; } - public static final long mod(long x, long y) { + public static long mod(long x, long y) { return (x - y * floorDivide(x, y)); } - public static final int mod(int x, int y) { + public static int mod(int x, int y) { return (x - y * floorDivide(x, y)); } - public static final int amod(int x, int y) { + public static int amod(int x, int y) { int z = mod(x, y); return (z == 0) ? y : z; } - public static final long amod(long x, long y) { + public static long amod(long x, long y) { long z = mod(x, y); return (z == 0) ? y : z; } @@ -127,7 +130,7 @@ public class CalendarUtils { /** * Mimics sprintf(buf, "%0*d", decaimal, width). */ - public static final StringBuilder sprintf0d(StringBuilder sb, int value, int width) { + public static StringBuilder sprintf0d(StringBuilder sb, int value, int width) { long d = value; if (d < 0) { sb.append('-'); @@ -146,7 +149,7 @@ public class CalendarUtils { return sb; } - public static final StringBuffer sprintf0d(StringBuffer sb, int value, int width) { + public static StringBuffer sprintf0d(StringBuffer sb, int value, int width) { long d = value; if (d < 0) { sb.append('-'); diff --git a/src/java.base/share/classes/sun/util/calendar/Gregorian.java b/src/java.base/share/classes/sun/util/calendar/Gregorian.java index d100687e4f5..c983814cecd 100644 --- a/src/java.base/share/classes/sun/util/calendar/Gregorian.java +++ b/src/java.base/share/classes/sun/util/calendar/Gregorian.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,21 +34,23 @@ import java.util.TimeZone; * @since 1.5 */ -public class Gregorian extends BaseCalendar { +public final class Gregorian extends BaseCalendar { - static class Date extends BaseCalendar.Date { - protected Date() { + static final class Date extends BaseCalendar.Date { + Date() { super(); } - protected Date(TimeZone zone) { + Date(TimeZone zone) { super(zone); } + @Override public int getNormalizedYear() { return getYear(); } + @Override public void setNormalizedYear(int normalizedYear) { setYear(normalizedYear); } @@ -57,30 +59,37 @@ public class Gregorian extends BaseCalendar { Gregorian() { } + @Override public String getName() { return "gregorian"; } + @Override public Date getCalendarDate() { return getCalendarDate(System.currentTimeMillis(), newCalendarDate()); } + @Override public Date getCalendarDate(long millis) { return getCalendarDate(millis, newCalendarDate()); } + @Override public Date getCalendarDate(long millis, CalendarDate date) { return (Date) super.getCalendarDate(millis, date); } + @Override public Date getCalendarDate(long millis, TimeZone zone) { return getCalendarDate(millis, newCalendarDate(zone)); } + @Override public Date newCalendarDate() { return new Date(); } + @Override public Date newCalendarDate(TimeZone zone) { return new Date(zone); } diff --git a/src/java.base/share/classes/sun/util/calendar/ImmutableGregorianDate.java b/src/java.base/share/classes/sun/util/calendar/ImmutableGregorianDate.java index 3d9b2da548a..4836cab9886 100644 --- a/src/java.base/share/classes/sun/util/calendar/ImmutableGregorianDate.java +++ b/src/java.base/share/classes/sun/util/calendar/ImmutableGregorianDate.java @@ -25,192 +25,238 @@ package sun.util.calendar; +import java.util.Objects; import java.util.TimeZone; -class ImmutableGregorianDate extends BaseCalendar.Date { +/* + * This class is immutable, and thus any methods from the base classes + * that can modify the state are overridden to throw an exception. + */ +final class ImmutableGregorianDate extends BaseCalendar.Date { private final BaseCalendar.Date date; ImmutableGregorianDate(BaseCalendar.Date date) { - if (date == null) { - throw new NullPointerException(); - } - this.date = date; + this.date = Objects.requireNonNull(date); } + @Override public Era getEra() { return date.getEra(); } + @Override public CalendarDate setEra(Era era) { unsupported(); return this; } + @Override public int getYear() { return date.getYear(); } + @Override public CalendarDate setYear(int year) { unsupported(); return this; } + @Override public CalendarDate addYear(int n) { unsupported(); return this; } + @Override public boolean isLeapYear() { return date.isLeapYear(); } + @Override void setLeapYear(boolean leapYear) { unsupported(); } + @Override public int getMonth() { return date.getMonth(); } + @Override public CalendarDate setMonth(int month) { unsupported(); return this; } + @Override public CalendarDate addMonth(int n) { unsupported(); return this; } + @Override public int getDayOfMonth() { return date.getDayOfMonth(); } + @Override public CalendarDate setDayOfMonth(int date) { unsupported(); return this; } + @Override public int getDayOfWeek() { return date.getDayOfWeek(); } + @Override public int getHours() { return date.getHours(); } + @Override public CalendarDate setHours(int hours) { unsupported(); return this; } + @Override public CalendarDate addHours(int n) { unsupported(); return this; } + @Override public int getMinutes() { return date.getMinutes(); } + @Override public CalendarDate setMinutes(int minutes) { unsupported(); return this; } + @Override public int getSeconds() { return date.getSeconds(); } + @Override public CalendarDate setSeconds(int seconds) { unsupported(); return this; } + @Override public int getMillis() { return date.getMillis(); } + @Override public CalendarDate setMillis(int millis) { unsupported(); return this; } + @Override public long getTimeOfDay() { return date.getTimeOfDay(); } + @Override public CalendarDate setDate(int year, int month, int dayOfMonth) { unsupported(); return this; } + @Override public CalendarDate setTimeOfDay(int hours, int minutes, int seconds, int millis) { unsupported(); return this; } + @Override protected void setTimeOfDay(long fraction) { unsupported(); } + @Override public boolean isNormalized() { return date.isNormalized(); } + @Override public boolean isDaylightTime() { return date.isDaylightTime(); } + @Override public TimeZone getZone() { return date.getZone(); } + @Override public CalendarDate setZone(TimeZone zoneinfo) { unsupported(); return this; } + @Override public boolean isSameDate(CalendarDate date) { return date.isSameDate(date); } + @Override public boolean equals(Object obj) { if (this == obj) { return true; } - if (!(obj instanceof ImmutableGregorianDate)) { + if (obj instanceof ImmutableGregorianDate igd) { + return date.equals(igd.date); + } else { return false; } - return date.equals(((ImmutableGregorianDate) obj).date); } + @Override public int hashCode() { return date.hashCode(); } + @Override public Object clone() { return super.clone(); } + @Override public String toString() { return date.toString(); } + @Override protected void setDayOfWeek(int dayOfWeek) { unsupported(); } + @Override protected void setNormalized(boolean normalized) { unsupported(); } + @Override public int getZoneOffset() { return date.getZoneOffset(); } + @Override protected void setZoneOffset(int offset) { unsupported(); } + @Override public int getDaylightSaving() { return date.getDaylightSaving(); } + @Override protected void setDaylightSaving(int daylightSaving) { unsupported(); } + @Override public int getNormalizedYear() { return date.getNormalizedYear(); } + @Override public void setNormalizedYear(int normalizedYear) { unsupported(); } diff --git a/src/java.base/share/classes/sun/util/calendar/JulianCalendar.java b/src/java.base/share/classes/sun/util/calendar/JulianCalendar.java index 8129090d295..49bdaa60cd9 100644 --- a/src/java.base/share/classes/sun/util/calendar/JulianCalendar.java +++ b/src/java.base/share/classes/sun/util/calendar/JulianCalendar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import java.util.TimeZone; * @author Masayoshi Okutsu * @since 1.5 */ -public class JulianCalendar extends BaseCalendar { +public final class JulianCalendar extends BaseCalendar { private static final int BCE = 0; private static final int CE = 1; @@ -44,17 +44,18 @@ public class JulianCalendar extends BaseCalendar { }; private static final int JULIAN_EPOCH = -1; - private static class Date extends BaseCalendar.Date { - protected Date() { + static final class Date extends BaseCalendar.Date { + Date() { super(); setCache(1, -1L, 365); // January 1, 1 CE (Julian) } - protected Date(TimeZone zone) { + Date(TimeZone zone) { super(zone); setCache(1, -1L, 365); // January 1, 1 CE (Julian) } + @Override public Date setEra(Era era) { if (era == null) { throw new NullPointerException(); @@ -66,10 +67,11 @@ public class JulianCalendar extends BaseCalendar { return this; } - protected void setKnownEra(Era era) { + void setKnownEra(Era era) { super.setEra(era); } + @Override public int getNormalizedYear() { if (getEra() == eras[BCE]) { return 1 - getYear(); @@ -81,6 +83,7 @@ public class JulianCalendar extends BaseCalendar { // normalized years. This differs from "Calendrical // Calculations" in which the numbering is ..., -2, -1, 1, 2, // ... + @Override public void setNormalizedYear(int year) { if (year <= 0) { setYear(1 - year); @@ -91,6 +94,7 @@ public class JulianCalendar extends BaseCalendar { } } + @Override public String toString() { String time = super.toString(); time = time.substring(time.indexOf('T')); @@ -114,30 +118,37 @@ public class JulianCalendar extends BaseCalendar { setEras(eras); } + @Override public String getName() { return "julian"; } + @Override public Date getCalendarDate() { return getCalendarDate(System.currentTimeMillis(), newCalendarDate()); } + @Override public Date getCalendarDate(long millis) { return getCalendarDate(millis, newCalendarDate()); } + @Override public Date getCalendarDate(long millis, CalendarDate date) { return (Date) super.getCalendarDate(millis, date); } + @Override public Date getCalendarDate(long millis, TimeZone zone) { return getCalendarDate(millis, newCalendarDate(zone)); } + @Override public Date newCalendarDate() { return new Date(); } + @Override public Date newCalendarDate(TimeZone zone) { return new Date(zone); } @@ -145,6 +156,7 @@ public class JulianCalendar extends BaseCalendar { /** * @param jyear normalized Julian year */ + @Override public long getFixedDate(int jyear, int month, int dayOfMonth, BaseCalendar.Date cache) { boolean isJan1 = month == JANUARY && dayOfMonth == 1; @@ -182,6 +194,7 @@ public class JulianCalendar extends BaseCalendar { return days; } + @Override public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) { Date jdate = (Date) date; long fd = 4 * (fixedDate - JULIAN_EPOCH) + 1464; @@ -216,18 +229,18 @@ public class JulianCalendar extends BaseCalendar { /** * Returns the normalized Julian year number of the given fixed date. */ + @Override public int getYearFromFixedDate(long fixedDate) { - int year = (int) CalendarUtils.floorDivide(4 * (fixedDate - JULIAN_EPOCH) + 1464, 1461); - return year; + return (int) CalendarUtils.floorDivide(4 * (fixedDate - JULIAN_EPOCH) + 1464, 1461); } + @Override public int getDayOfWeek(CalendarDate date) { - // TODO: should replace this with a faster calculation, such - // as cache table lookup - long fixedDate = getFixedDate(date); - return getDayOfWeekFromFixedDate(fixedDate); + // TODO: should replace with faster calculation, e.g. cache table lookup + return getDayOfWeekFromFixedDate(getFixedDate(date)); } + @Override boolean isLeapYear(int jyear) { return CalendarUtils.isJulianLeapYear(jyear); } diff --git a/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java b/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java index 283adca6b59..cb567e8c052 100644 --- a/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java +++ b/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java @@ -36,7 +36,7 @@ import sun.security.action.GetPropertyAction; * @since 1.6 */ -public class LocalGregorianCalendar extends BaseCalendar { +public final class LocalGregorianCalendar extends BaseCalendar { private static final Era[] JAPANESE_ERAS = { new Era("Meiji", "M", -3218832000000L, true), new Era("Taisho", "T", -1812153600000L, true), @@ -63,13 +63,14 @@ public class LocalGregorianCalendar extends BaseCalendar { private String name; private Era[] eras; - public static class Date extends BaseCalendar.Date { + // Used within java.time and java.util + public static final class Date extends BaseCalendar.Date { - protected Date() { + Date() { super(); } - protected Date(TimeZone zone) { + Date(TimeZone zone) { super(zone); }