// Version: Feb 2020 // // The following Dart 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. // class NexCalendar { // Weekday = Day of the Week (1 = Monday ... 7 = Sunday, 8 = Sunday) // Yearday = Ordinal Day of the Year (1 ... 365, 366 = Leap Sunday) static var maxDaysInYear = 366; // 366 is equal to the Leap Sunday static var daysByWeek35 = 35 * 7 + 1; // Week 35 is the annual long week with 8 days static var daysInMonths = [ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; static var daysByMonths = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ]; static bool invalidInt(int x, int max) { return (x < 1 || x > max); } static int getYeardayFromMonthDay(month, day) // month = 1 to 12, day = 1 to 31 { if (invalidInt(month, 12) || invalidInt(day, daysInMonths[month])) return 0; return (daysByMonths[month - 1] + day); } static MapgetMonthDay(int yearday) { if (invalidInt(yearday, maxDaysInYear)) return {"month": 0, "day": 0}; var 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++; var day = yearday - daysByMonths[month - 1]; return { "month": month, "day": day }; } static int getYeardayFromWeekDate(int week, int weekday) // week = 1 to 52, weekday = 1 to 7 or 8 for week 35 or 52. { if (week == 35 && weekday == 8) return daysByWeek35; if (week == 52 && weekday == 8) return maxDaysInYear; if (invalidInt(week, 52) || invalidInt(weekday, 7)) return 0; var yearday = (week - 1) * 7 + weekday; if (week > 35) yearday++; return yearday; } static Map getWeekDate(yearday) { if (invalidInt(yearday, maxDaysInYear)) return {"week": 0, "weekday": 0}; // Unknown if (yearday == maxDaysInYear) return {"week": 52, "weekday": 8}; // The last week if (yearday == daysByWeek35) return {"week": 35, "weekday": 8}; // The last week if (yearday >= daysByWeek35) yearday--; var week = (yearday / 7).ceil(); var weekday = yearday - ((week - 1) * 7); return { "week": week, "weekday": weekday }; } static Map getWeekDateFromMonthDay(int month, int day) { return getWeekDate(getYeardayFromMonthDay(month, day));} static Map getMonthDayFromWeekDate(int week, int weekday) { return getMonthDay(getYeardayFromWeekDate(week, weekday));} static Map getWeekdayName(week, weekday) { if ((week == 35 || week == 52) && weekday == 8) weekday = 7; // Special Sunday if (invalidInt(week, 52) || invalidInt(weekday, 7)) return null; // if no 'package:intl/intl.dart': var longNames = ["","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]; var shortNames = ["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"]; var longName = longNames[weekday]; var shortName = shortNames[weekday]; // if the package:intl is available: // import 'package:intl/intl.dart'; // var date = new DateTime(2001,1,weekday); // 1 to 7 = Monday to Sunday // var longName = new DateFormat("EEEE").format(date); // var shortName = new DateFormat("E").format(date); return { "longName": longName, "shortName": shortName }; } static bool isLeapYear(int year) { if( invalidInt(year,9999)) return false; return ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)); } static int getYeardayFromDate(DateTime date) { int year = date.year; int month = date.month; int day = date.day; int yearday = getYeardayFromMonthDay(month, day); if( !isLeapYear(year) && month > 2) yearday--; return yearday; } static DateTime newDate(int year, [ int month = 1, int day = 1, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0, bool utc = false ]) { if (!isLeapYear(year)) { if (invalidInt(month, 12)) return null; if (invalidInt(day, daysInMonths[month])) return null; 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++; } if( utc ) return new DateTime.utc(year, month, day, hour, minute, second, millisecond, microsecond); else return new DateTime(year, month, day, hour, minute, second, millisecond, microsecond); } static String toDateString(DateTime date) { if( date == null ) return ""; int year = date.year; int month = date.month; int day = date.day; if (!isLeapYear(year) && month > 2) { // the previous day day--; if (day == 0) day = daysInMonths[--month]; } var week = getWeekDateFromMonthDay(month, day); var weekdayName = getWeekdayName(week["week"], week["weekday"]); String long = weekdayName["longName"]; String short = weekdayName["shortName"]; String y = year.toString(); String m = month.toString(); String d = day.toString(); String h = date.hour.toString(); String min = date.minute.toString(); String sec = date.second.toString(); String ms = date.millisecond.toString(); if (date.isUtc) { return "$y-$m-$d $long $short $h:$min:$sec.$ms Z"; } else { return "$y-$m-$d $long $short $h:$min:$sec.$ms"; } } } // e.g. void main() { // e.g. var date = NexCalendar.getMonthDay(246); print("Month: ${date["month"]} day: ${date["day"]}"); var weekdate = NexCalendar.getWeekDate(246); print("Week: ${weekdate["week"]} Weekday: ${weekdate["weekday"]}"); var weekdayName = NexCalendar.getWeekdayName(35, 7); print("Long name: ${weekdayName["longName"]} Short name: ${weekdayName["shortName"]}"); print(NexCalendar.toDateString(DateTime.now())); var feb29 = NexCalendar.newDate(2021,2,29); print(feb29.toString()); print(NexCalendar.toDateString(feb29)); var lastdate = DateTime(2021,12,31); print("Yearday is " + NexCalendar.getYeardayFromDate(lastdate).toString()); } // Copyright © 2020 Dr. Donny C.F. Lai & Justin J.S. Lai. All Rights Reserved.