mirror of
https://github.com/nisrulz/flutter-examples.git
synced 2025-05-20 22:46:24 +08:00
153 lines
5.4 KiB
Dart
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;
|
|
}
|