LCOV - code coverage report
Current view: top level - src - utils.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 43 82 52.4 %
Date: 2022-02-12 14:49:12 Functions: 0 0 -

          Line data    Source code
       1             : /// Bunch of useful functions for date pickers.
       2             : class DatePickerUtils {
       3             :   /// Returns if two objects have same year, month and day.
       4             :   /// Time doesn't matter.
       5           4 :   static bool sameDate(DateTime dateTimeOne, DateTime dateTimeTwo) =>
       6          12 :       dateTimeOne.year == dateTimeTwo.year &&
       7          12 :       dateTimeOne.month == dateTimeTwo.month &&
       8          12 :       dateTimeOne.day == dateTimeTwo.day;
       9             : 
      10             :   /// Returns if two objects have same year and month.
      11             :   /// Day and time don't matter/
      12           1 :   static bool sameMonth(DateTime dateTimeOne, DateTime dateTimeTwo) =>
      13           3 :       dateTimeOne.year == dateTimeTwo.year &&
      14           3 :       dateTimeOne.month == dateTimeTwo.month;
      15             : 
      16             :   // Do not use this directly - call getDaysInMonth instead.
      17             :   static const List<int> _daysInMonth = <int>[
      18             :     31,
      19             :     -1,
      20             :     31,
      21             :     30,
      22             :     31,
      23             :     30,
      24             :     31,
      25             :     31,
      26             :     30,
      27             :     31,
      28             :     30,
      29             :     31
      30             :   ];
      31             : 
      32             :   /// Returns the number of days in a month, according to the proleptic
      33             :   /// Gregorian calendar.
      34             :   ///
      35             :   /// This applies the leap year logic introduced by the Gregorian reforms of
      36             :   /// 1582. It will not give valid results for dates prior to that time.
      37           1 :   static int getDaysInMonth(int year, int month) {
      38           1 :     if (month == DateTime.february) {
      39             :       final bool isLeapYear =
      40           0 :           (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
      41             :       return isLeapYear ? 29 : 28;
      42             :     }
      43           2 :     return _daysInMonth[month - 1];
      44             :   }
      45             : 
      46             :   /// Returns number of months between [startDate] and [endDate]
      47           0 :   static int monthDelta(DateTime startDate, DateTime endDate) =>
      48           0 :       (endDate.year - startDate.year) * 12 + endDate.month - startDate.month;
      49             : 
      50             :   /// Add months to a month truncated date.
      51           0 :   static DateTime addMonthsToMonthDate(DateTime monthDate, int monthsToAdd) =>
      52             :       // year is switched automatically if new month > 12
      53           0 :       DateTime(monthDate.year, monthDate.month + monthsToAdd);
      54             : 
      55             :   /// Returns number of years between [startDate] and [endDate]
      56           0 :   static int yearDelta(DateTime startDate, DateTime endDate) =>
      57           0 :       endDate.year - startDate.year;
      58             : 
      59             :   /// Returns start of the first day of the week with given day.
      60             :   ///
      61             :   /// Start of the week calculated using firstDayIndex which is int from 0 to 6
      62             :   /// where 0 points to Sunday and 6 points to Saturday.
      63             :   /// (according to MaterialLocalization.firstDayIfWeekIndex)
      64           1 :   static DateTime getFirstDayOfWeek(DateTime day, int firstDayIndex) {
      65             :     // from 1 to 7 where 1 points to Monday and 7 points to Sunday
      66           1 :     int weekday = day.weekday;
      67             : 
      68             :     // to match weekdays where Sunday is 7 not 0
      69           1 :     if (firstDayIndex == 0) firstDayIndex = 7;
      70             : 
      71           1 :     int diff = weekday - firstDayIndex;
      72           1 :     if (diff < 0) diff = 7 + diff;
      73             : 
      74           1 :     DateTime firstDayOfWeek = DateTime(
      75           1 :       day.year,
      76           1 :       day.month,
      77           2 :       day.day - diff,
      78           1 :       day.hour,
      79           1 :       day.minute,
      80           1 :       day.second,
      81             :     );
      82           1 :     firstDayOfWeek = startOfTheDay(firstDayOfWeek);
      83             : 
      84             :     return firstDayOfWeek;
      85             :   }
      86             : 
      87             :   /// Returns end of the last day of the week with given day.
      88             :   ///
      89             :   /// Start of the week calculated using firstDayIndex which is int from 0 to 6
      90             :   /// where 0 points to Sunday and 6 points to Saturday.
      91             :   /// (according to MaterialLocalization.firstDayIfWeekIndex)
      92           1 :   static DateTime getLastDayOfWeek(DateTime day, int firstDayIndex) {
      93             :     // from 1 to 7 where 1 points to Monday and 7 points to Sunday
      94           1 :     int weekday = day.weekday;
      95             : 
      96             :     // to match weekdays where Sunday is 7 not 0
      97           1 :     if (firstDayIndex == 0) firstDayIndex = 7;
      98             : 
      99           1 :     int lastDayIndex = firstDayIndex - 1;
     100           1 :     if (lastDayIndex == 0) lastDayIndex = 7;
     101             : 
     102           1 :     int diff = lastDayIndex - weekday;
     103           1 :     if (diff < 0) diff = 7 + diff;
     104             : 
     105           1 :     DateTime lastDayOfWeek = DateTime(
     106           1 :       day.year,
     107           1 :       day.month,
     108           2 :       day.day + diff,
     109           1 :       day.hour,
     110           1 :       day.minute,
     111           1 :       day.second,
     112             :     );
     113           1 :     lastDayOfWeek = endOfTheDay(lastDayOfWeek);
     114             : 
     115             :     return lastDayOfWeek;
     116             :   }
     117             : 
     118             :   /// Returns end of the given day.
     119             :   ///
     120             :   /// End time is 1 millisecond before start of the next day.
     121           5 :   static DateTime endOfTheDay(DateTime date) {
     122          25 :     DateTime tomorrowStart = DateTime(date.year, date.month, date.day + 1);
     123           5 :     DateTime result = tomorrowStart.subtract(const Duration(milliseconds: 1));
     124             : 
     125             :     return result;
     126             :   }
     127             : 
     128             :   /// Returns start of the given day.
     129             :   ///
     130             :   /// Start time is 00:00:00.
     131           5 :   static DateTime startOfTheDay(DateTime date) =>
     132          20 :       DateTime(date.year, date.month, date.day);
     133             : 
     134             :   /// Returns first shown date for the [curMonth].
     135             :   ///
     136             :   /// First shown date is not always 1st day of the [curMonth].
     137             :   /// It can be day from previous month if [showEndOfPrevMonth] is true.
     138             :   ///
     139             :   /// If [showEndOfPrevMonth] is true empty day cells before 1st [curMonth]
     140             :   /// are filled with days from the previous month.
     141           0 :   static DateTime firstShownDate({
     142             :     required DateTime curMonth,
     143             :     required bool showEndOfPrevMonth,
     144             :     required int firstDayOfWeekFromSunday,
     145             :   }) {
     146           0 :     DateTime result = DateTime(curMonth.year, curMonth.month, 1);
     147             : 
     148             :     if (showEndOfPrevMonth) {
     149           0 :       int firstDayOffset = computeFirstDayOffset(
     150           0 :           curMonth.year, curMonth.month, firstDayOfWeekFromSunday);
     151           0 :       if (firstDayOffset == 0) return result;
     152             : 
     153           0 :       int prevMonth = curMonth.month - 1;
     154           0 :       if (prevMonth < 1) prevMonth = 12;
     155             : 
     156           0 :       int prevYear = prevMonth == 12 ? curMonth.year - 1 : curMonth.year;
     157             : 
     158           0 :       int daysInPrevMonth = getDaysInMonth(prevYear, prevMonth);
     159           0 :       int firstShownDay = daysInPrevMonth - firstDayOffset + 1;
     160           0 :       result = DateTime(prevYear, prevMonth, firstShownDay);
     161             :     }
     162             : 
     163             :     return result;
     164             :   }
     165             : 
     166             :   /// Returns last shown date for the [curMonth].
     167             :   ///
     168             :   /// Last shown date is not always last day of the [curMonth].
     169             :   /// It can be day from next month if [showStartNextMonth] is true.
     170             :   ///
     171             :   /// If [showStartNextMonth] is true empty day cells after last day
     172             :   /// of [curMonth] are filled with days from the next month.
     173           0 :   static DateTime lastShownDate({
     174             :     required DateTime curMonth,
     175             :     required bool showStartNextMonth,
     176             :     required int firstDayOfWeekFromSunday,
     177             :   }) {
     178           0 :     int daysInCurMonth = getDaysInMonth(curMonth.year, curMonth.month);
     179           0 :     DateTime result = DateTime(curMonth.year, curMonth.month, daysInCurMonth);
     180             : 
     181             :     if (showStartNextMonth) {
     182           0 :       int firstDayOffset = computeFirstDayOffset(
     183           0 :           curMonth.year, curMonth.month, firstDayOfWeekFromSunday);
     184             : 
     185           0 :       int totalDays = firstDayOffset + daysInCurMonth;
     186           0 :       int trailingDaysCount = 7 - totalDays % 7;
     187           0 :       bool fullWeekTrailing = trailingDaysCount == 7;
     188             :       if (fullWeekTrailing) return result;
     189             : 
     190           0 :       result = DateTime(curMonth.year, curMonth.month + 1, trailingDaysCount);
     191             :     }
     192             : 
     193             :     return result;
     194             :   }
     195             : 
     196             :   /// Computes the offset from the first day of week that the first day of the
     197             :   /// [month] falls on.
     198             :   ///
     199             :   /// For example, September 1, 2017 falls on a Friday, which in the calendar
     200             :   /// localized for United States English appears as:
     201             :   ///
     202             :   /// ```
     203             :   /// S M T W T F S
     204             :   /// _ _ _ _ _ 1 2
     205             :   /// ```
     206             :   ///
     207             :   /// The offset for the first day of the months is the number of leading blanks
     208             :   /// in the calendar, i.e. 5.
     209             :   ///
     210             :   /// The same date localized for the Russian calendar has a different offset,
     211             :   /// because the first day of week is Monday rather than Sunday:
     212             :   ///
     213             :   /// ```
     214             :   /// M T W T F S S
     215             :   /// _ _ _ _ 1 2 3
     216             :   /// ```
     217             :   ///
     218             :   /// So the offset is 4, rather than 5.
     219             :   ///
     220             :   /// This code consolidates the following:
     221             :   ///
     222             :   /// - [DateTime.weekday] provides a 1-based index into days of week, with 1
     223             :   ///   falling on Monday.
     224             :   /// - MaterialLocalizations.firstDayOfWeekIndex provides a 0-based index
     225             :   ///   into the MaterialLocalizations.narrowWeekdays list.
     226             :   /// - MaterialLocalizations.narrowWeekdays list provides localized names of
     227             :   ///   days of week, always starting with Sunday and ending with Saturday.
     228           0 :   static int computeFirstDayOffset(
     229             :       int year, int month, int firstDayOfWeekFromSunday) {
     230             :     // 0-based day of week, with 0 representing Monday.
     231           0 :     final int weekdayFromMonday = DateTime(year, month).weekday - 1;
     232             :     // firstDayOfWeekFromSunday recomputed to be Monday-based
     233           0 :     final int firstDayOfWeekFromMonday = (firstDayOfWeekFromSunday - 1) % 7;
     234             :     // Number of days between the first day of week appearing on the calendar,
     235             :     // and the day corresponding to the 1-st of the month.
     236           0 :     return (weekdayFromMonday - firstDayOfWeekFromMonday) % 7;
     237             :   }
     238             : 
     239             :   /// Returns earliest [DateTime] from the list.
     240             :   ///
     241             :   /// [dates] must not be null.
     242             :   /// In case it is null, [ArgumentError] will be thrown.
     243           0 :   static DateTime getEarliestFromList(List<DateTime> dates) {
     244           0 :     ArgumentError.checkNotNull(dates, "dates");
     245             : 
     246           0 :     return dates.fold(dates[0], getEarliest);
     247             :   }
     248             : 
     249             :   /// Returns latest [DateTime] from the list.
     250             :   ///
     251             :   /// [dates] must not be null.
     252             :   /// In case it is null, [ArgumentError] will be thrown.
     253           0 :   static DateTime getLatestFromList(List<DateTime> dates) {
     254           0 :     ArgumentError.checkNotNull(dates, "dates");
     255             : 
     256           0 :     return dates.fold(dates[0], getLatest);
     257             :   }
     258             : 
     259             :   /// Returns earliest [DateTime] from two.
     260             :   ///
     261             :   /// If two [DateTime]s is the same moment first ([a]) will be return.
     262           0 :   static DateTime getEarliest(DateTime a, DateTime b) => a.isBefore(b) ? a : b;
     263             : 
     264             :   /// Returns latest [DateTime] from two.
     265             :   ///
     266             :   /// If two [DateTime]s is the same moment first ([a]) will be return.
     267           0 :   static DateTime getLatest(DateTime a, DateTime b) => a.isAfter(b) ? a : b;
     268             : }

Generated by: LCOV version 1.15