0

I have a calendar in my Flutter App and I need to print a list of the weeks in the current month. But rather than starting on the 1st day of each month, it needs to start with the first Monday of the month (e.g. 05 April 2021 as the first Monday of April 2021). Then I need to print out the following weeks in that month, again starting from Monday. This includes the days of the next month that the final week of the current month follows on from (e.g. 26 April 2021 - 02 May 2021). It should print like this:

05 Apr - 11 Apr
12 Apr - 18 Apr
19 Apr - 25 Apr
26 Apr - 02 May
James 666
  • 1,560
  • 1
  • 15
  • 27

1 Answers1

4

Start by figuring out how to find how many days there are from a given weekday to the Monday on or after that day. Examples help; if the given weekday is:

  • Monday, add 0 days.
  • Tuesday, add 6 days.
  • Wednesday, add 5 days.
  • ... etc. ...
  • Sunday, add 1 day.

We could make a lookup table, but we also can devise that the offset (in days) from a given weekday to the Monday on or after that day has the form (7 - x) % 7 where x corresponds to the given weekday. We'd want that value to be 0 for Monday, 1 for Tuesday, and so on, until 6 for Sunday. Dart's DateTime.weekday uses values 1 (DateTime.monday) through 7 (DateTime.sunday), so we can easily map that to the value we want via DateTime.weekday - DateTime.monday.

Once we compute that offset, we can find the first day of the current month, add that offset to find the first Monday of the month, and then you can iteratively add 7 days until you reach the next month, and we can use DateFormat from package:intl to format the dates the way you want:

import 'package:intl/intl.dart';

String formatDate(DateTime dateTime) => DateFormat('dd MMM').format(dateTime);

void main() {
  var now = DateTime.now();

  var firstOfMonth = DateTime(now.year, now.month, 1);
  var firstMonday =
      firstOfMonth.addCalendarDays((7 - (firstOfMonth.weekday - DateTime.monday)) % 7);
  var currentMonday = firstMonday;
  while (currentMonday.month == now.month) {
    var nextMonday = currentMonday.addCalendarDays(7);
    var nextSunday = nextMonday.addCalendarDays(-1);
    print('${formatDate(currentMonday)} - ${formatDate(nextSunday)}');
    currentMonday = nextMonday;
  }
}

See https://stackoverflow.com/a/68216029/ for the implementation of the addCalendarDays extension method.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • What happens if it is the last day of a month and you add a day? Also, if you make a subtract method to subtract number of days and it is the first of a month that you want to subtract a day from. – John Nov 09 '21 at 04:44
  • 1
    @John `DateTime` object itself will correct the month automatically. For example, `DateTime(2021, 1, 0)` will create a `DateTime` object for 2020-12-31. – jamesdlin Nov 09 '21 at 05:06
  • what about DateTime(2021, 0, 0) and DateTime(2021, -1, 0)? – John Nov 09 '21 at 05:15
  • 1
    @John I don't see how those examples are relevant since the code I posted would never construct such objects. Regardless, it's trivial to try it and observe the results yourself. (`DateTime(2021, 0, 1)` constructs an object for 2020-12-01; `DateTime(2021, 0, 0)` constructs an object for the day before that (2020-11-30); `DateTime(2021, -1, 1)` constructs an object for 2020-11-01; `DateTime(2021, -1, 0)` constructs an object for the day before that (2020-10-31).) – jamesdlin Nov 09 '21 at 05:37