Files
2022-10-22 20:29:43 +02:00

153 lines
5.4 KiB
Dart

/// Bunch of useful functions for date pickers.
class DateTimeUtils {
/// Returns if two objects have same year, month and day.
/// Time doesn't matter.
static bool sameDate(DateTime dateTimeOne, DateTime dateTimeTwo) =>
dateTimeOne.year == dateTimeTwo.year &&
dateTimeOne.month == dateTimeTwo.month &&
dateTimeOne.day == dateTimeTwo.day;
/// Returns if two objects have same year and month.
/// Day and time don't matter/
static bool sameMonth(DateTime dateTimeOne, DateTime dateTimeTwo) =>
dateTimeOne.year == dateTimeTwo.year
&& dateTimeOne.month == dateTimeTwo.month;
/// Returns number of months between [startDate] and [endDate]
static int monthDelta(DateTime startDate, DateTime endDate) =>
(endDate.year - startDate.year) * 12 +
endDate.month -
startDate.month;
/// Add months to a month truncated date.
static DateTime addMonthsToMonthDate(DateTime monthDate, int monthsToAdd) =>
// year is switched automatically if new month > 12
DateTime(monthDate.year, monthDate.month + monthsToAdd);
/// Returns number of years between [startDate] and [endDate]
static int yearDelta(DateTime startDate, DateTime endDate) =>
endDate.year - startDate.year;
/// Returns start of the first day of the week with given day.
///
/// Start of the week calculated using firstDayIndex which is int from 0 to 6
/// where 0 points to Sunday and 6 points to Saturday.
/// (according to MaterialLocalization.firstDayIfWeekIndex)
static DateTime getFirstDayOfWeek(DateTime day, int firstDayIndex) {
// from 1 to 7 where 1 points to Monday and 7 points to Sunday
int weekday = day.weekday;
// to match weekdays where Sunday is 7 not 0
if (firstDayIndex == 0) firstDayIndex = 7;
int diff = weekday - firstDayIndex;
if (diff < 0) diff = 7 + diff;
DateTime firstDayOfWeek = day.subtract(Duration(days: diff));
firstDayOfWeek = startOfTheDay(firstDayOfWeek);
return firstDayOfWeek;
}
/// Returns end of the last day of the week with given day.
///
/// Start of the week calculated using firstDayIndex which is int from 0 to 6
/// where 0 points to Sunday and 6 points to Saturday.
/// (according to MaterialLocalization.firstDayIfWeekIndex)
static DateTime getLastDayOfWeek(DateTime day, int firstDayIndex) {
// from 1 to 7 where 1 points to Monday and 7 points to Sunday
int weekday = day.weekday;
// to match weekdays where Sunday is 7 not 0
if (firstDayIndex == 0) firstDayIndex = 7;
int lastDayIndex = firstDayIndex - 1;
if (lastDayIndex == 0) lastDayIndex = 7;
int diff = lastDayIndex - weekday;
if (diff < 0) diff = 7 + diff;
DateTime lastDayOfWeek = day.add(Duration(days: diff));
lastDayOfWeek = endOfTheDay(lastDayOfWeek);
return lastDayOfWeek;
}
/// Returns end of the given day.
///
/// End time is 1 millisecond before start of the next day.
static DateTime endOfTheDay(DateTime date) =>
DateTime(date.year, date.month, date.day)
.add(const Duration(days: 1))
.subtract(const Duration(milliseconds: 1));
/// Returns start of the given day.
///
/// Start time is 00:00:00.
static DateTime startOfTheDay(DateTime date) =>
DateTime(date.year, date.month, date.day);
/// Computes the offset from the first day of week that the first day of the
/// [month] falls on.
///
/// For example, September 1, 2017 falls on a Friday, which in the calendar
/// localized for United States English appears as:
///
/// ```
/// S M T W T F S
/// _ _ _ _ _ 1 2
/// ```
///
/// The offset for the first day of the months is the number of leading blanks
/// in the calendar, i.e. 5.
///
/// The same date localized for the Russian calendar has a different offset,
/// because the first day of week is Monday rather than Sunday:
///
/// ```
/// M T W T F S S
/// _ _ _ _ 1 2 3
/// ```
///
/// So the offset is 4, rather than 5.
///
/// This code consolidates the following:
///
/// - [DateTime.weekday] provides a 1-based index into days of week, with 1
/// falling on Monday.
/// - MaterialLocalizations.firstDayOfWeekIndex provides a 0-based index
/// into the MaterialLocalizations.narrowWeekdays list.
/// - MaterialLocalizations.narrowWeekdays list provides localized names of
/// days of week, always starting with Sunday and ending with Saturday.
static int computeFirstDayOffset(
int year, int month, int firstDayOfWeekFromSunday) {
// 0-based day of week, with 0 representing Monday.
final int weekdayFromMonday = DateTime(year, month).weekday - 1;
// firstDayOfWeekFromSunday recomputed to be Monday-based
final int firstDayOfWeekFromMonday = (firstDayOfWeekFromSunday - 1) % 7;
// Number of days between the first day of week appearing on the calendar,
// and the day corresponding to the 1-st of the month.
return (weekdayFromMonday - firstDayOfWeekFromMonday) % 7;
}
/// Returns earliest [DateTime] from the list.
///
/// [dates] must not be null.
/// In case it is null, [ArgumentError] will be thrown.
static DateTime getEarliestFromList(List<DateTime> dates) {
ArgumentError.checkNotNull(dates, "dates");
return dates.fold(dates[0], getEarliest);
}
/// Returns earliest [DateTime] from two.
///
/// If two [DateTime]s is the same moment first ([a]) will be return.
static DateTime getEarliest(DateTime a, DateTime b)
=> a.isBefore(b) ? a : b;
}