// Version: Feb 2020 // // The following Java program illustrates how easy it is to apply NexCalendar: // // Since software stores dates by its ordinal days from a special date, // it is easy to convert any Gregorian date to NexCalendar date. // import java.util.*; import java.time.*; import java.time.format.*; import java.text.DateFormatSymbols; import java.io.*; public class NexCalendar { // Weekday = Day of the Week (1 = Monday ... 7 = Sunday, 8 = Sunday) // Yearday = Ordinal Day of the Year (1 ... 365, 366 = Leap Sunday) public static final int maxdaysInYear = 366; // 366 is equal to the Leap Sunday public static final int daysByWeek35 = 35 * 7 + 1; // It is the annual long week with 8 days public static final int[] daysInMonths = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; public static final int[] daysByMonths = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; private static boolean invalidInt(int x, int max) { return (x < 1 || x > max); } public static int getYeardayFromMonthDay(int month, int day) { if (invalidInt(month, 12) || invalidInt(day, daysInMonths[month])) return 0; return (daysByMonths[month - 1] + day); } public static int[] getMonthDay(int yearday) // [0] = month, [1] = day { if (invalidInt(yearday, maxdaysInYear)) return new int[] {0,0}; int month = 2; if (yearday > daysByMonths[4]) month = 6; if (yearday > daysByMonths[8]) month = 10; if (yearday > daysByMonths[month]) month++; else month--; if (yearday > daysByMonths[month]) month++; return new int[] {month, yearday - daysByMonths[month - 1]}; } public static int getYeardayFromWeekDate(int week, int weekday) { if (week == 35 && weekday == 8) return daysByWeek35; if (week == 52 && weekday == 8) return maxdaysInYear; if (invalidInt(week, 52) || invalidInt(weekday, 7)) return 0; int yearday = (week - 1) * 7 + weekday; if (week > 35) yearday++; return yearday; } public static int[] getWeekDate(int yearday) // [0] = week, [1] = weekday { if (invalidInt(yearday, maxdaysInYear)) return new int[] {0, 0}; // Unknown if (yearday == maxdaysInYear) return new int[] {52, 8}; // The last week if (yearday == daysByWeek35) return new int[] {35, 8}; // The last week if (yearday >= daysByWeek35) yearday--; int week = (1 + (yearday - 1) / 7); int weekday = yearday - ((week - 1) * 7); return new int[] {week, weekday}; } public static int[] getWeekDateFromMonthDay(int month, int day) // [0] = week, [1] = weekday { return getWeekDate(getYeardayFromMonthDay(month, day)); } public static int[] getMonthDayFromWeekDate(int week, int weekday) // [0] = month, [1] = day { return getMonthDay(getYeardayFromWeekDate(week, weekday)); } public static String[] getWeekdayName(int week, int weekday) // [0] = LongName, [1] = ShortName { if ((week == 35 || week == 52) && weekday == 8) weekday = 7; // Special Sunday if (invalidInt(week, 52) || invalidInt(weekday, 7)) return new String[] {"", ""}; if (weekday == 7) weekday = 0; // Sunday is 0 weekday++; // Sunday = 1, Saturday = 7 String longName = DateFormatSymbols.getInstance().getWeekdays()[weekday]; String shortName = DateFormatSymbols.getInstance().getShortWeekdays()[weekday]; return new String[] {longName, shortName}; } public static boolean isLeapYear(int year) { return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0); } public static LocalDate newLocalDate(int year, int month, int day) { if (!isLeapYear(year)) { if (invalidInt(month, 12)) throw new UncheckedIOException(new IOException("invalid Month")); if (invalidInt(day, daysInMonths[month])) throw new UncheckedIOException(new IOException("invalid Day")); if (month == 12 && day == 31) ; // set the last day of the year else if (month > 1 && day == daysInMonths[month]) { month++; day = 1; } else if (month > 2) day++; } return LocalDate.of(year, month, day); } public static Date newDate(int year, int month, int day) { LocalDate localDate = newLocalDate(year, month, day); return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); } public static String toString(LocalDate date, String format) { String d = "@"; int diff = 0; int day = date.getDayOfMonth(); int month = date.getMonthValue(); int year = date.getYear(); int dayOfYear = date.getDayOfYear(); int[] weekDate = NexCalendar.getWeekDate(dayOfYear); String[] weekdayName = NexCalendar.getWeekdayName(weekDate[0], weekDate[1]); if (!isLeapYear(year) && month > 2) { // the previous day diff = -1; day--; if (day == 0) day = NexCalendar.daysInMonths[(month - 1)]; } date = date.plusDays(diff); format = format.replaceAll("d",d); format = format.replaceAll("EEEE", d+d+d+d); format = format.replaceAll("E+", d+d+d); String output = date.format(DateTimeFormatter.ofPattern(format)); output = output.replaceAll(d + d + d + d, weekdayName[0]); // longName output = output.replaceAll(d + d + d, weekdayName[1]); // shortName output = output.replaceAll(d + d, (day < 10? "0"+day : ""+day)); output = output.replaceAll(d, ""+day); return output; } public static String toString(Date date, String format) { LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); return toString(localDate, format); } // e.g. public static void main(String[] args) { LocalDate date = NexCalendar.newLocalDate(2021,2,29); int[] monthDay = NexCalendar.getMonthDay(date.getDayOfYear()); int[] weekDate = NexCalendar.getWeekDate(date.getDayOfYear()); String[] weekdayName = NexCalendar.getWeekdayName(weekDate[0], weekDate[1]); System.out.println("Month: " + monthDay[0] + " Day: " + monthDay[1]); System.out.println("Week: " + weekDate[0] + " Weekday: " + weekDate[1]); System.out.println("It is " + weekdayName[0] + " (" + weekdayName[1] + ")"); System.out.println(NexCalendar.toString(date,"d-MMM-yyyy d dd E EEEE")); } } // Copyright © 2020 Dr. Donny C.F. Lai & Justin J.S. Lai. All Rights Reserved.