```    // 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 Map getMonthDay(int yearday)
{
if (invalidInt(yearday, maxDaysInYear)) return {"month": 0, "day": 0};
var month = 2;
if (yearday > daysByMonths) month = 6;
if (yearday > daysByMonths) 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());
}