How to get a list of each week in a time range with Dart?

2,357

Solution 1

As Stefano wrote, it's good to create a class with a structure to be able to achieve your goals. My suggestion is a little more simple since I just wrote a method you could use. You could even create an extension on the DateTime class and use that in the future, or implement it in a static class, or add it to an instance class. Here is the complete example that works on DartPad:

void main() {
  var weeks = getWeeksForRange(DateTime.utc(2020,08,12), DateTime.utc(2020,10,12));
  
  print(weeks);
}

List<List<DateTime>> getWeeksForRange(DateTime start, DateTime end) {
  var result = List<List<DateTime>>();
  
  var date = start;
  var week = List<DateTime>();
  
  while(date.difference(end).inDays <= 0) {   
    // start new week on Monday
    if (date.weekday == 1 && week.length > 0) {
      print('Date $date is a Monday');
      result.add(week);
      week = List<DateTime>();
    } 
    
    week.add(date);
    
    date = date.add(const Duration(days: 1));
  }
  
  result.add(week);
  
  return result;
}

This method can take any two dates and create a list of lists (weeks) of DateTime objects. Since in the result you will have many DateTime results, you can then map them however you want since they will have all information about its date, year, weekday and will keep the formatting feature.

Solution 2

One first step could be to create a Class according to your needs:

class Day {
  final DateTime dateTime;
  Day({
    this.dateTime,
  });

  String get day => DateFormat('EEEE').format(dateTime);
  String get date => DateFormat('yMMMd').format(dateTime);

  Map<String, String> toMap() => {'dayName': day, 'date': date};
}

We can construct the Class above just with a DateTime and from it, we can derive the day and date using DateFormat in the getters:

 String get day => DateFormat('EEEE').format(dateTime); // returns "Friday" for example
 String get date => DateFormat('yMMMd').format(dateTime); // returns "Jun 13, 2021" for example

The toMap() method allows use to easily convert the Class to a Map<String, String>:

Map<String, String> toMap() => {'dayName': day, 'date': date};

We now need to store the Days in a List<Day>:

List<Day> days = [];

By iterating from the starting DateTime to the ending DateTime:

DateTime now = DateTime.now(); // as an example

DateTime start = now;
DateTime after = now.add(Duration(days: 180));

DateTime iterator = start;
List<Day> days = [];

while (iterator.isBefore(after)) {
 days.add(Day(dateTime: iterator));
 iterator = iterator.add(Duration(days: 1));
}

A full source code for the scenario outlined can be found below:

import 'package:intl/intl.dart';

class Day {
  final DateTime dateTime;
  Day({
    this.dateTime,
  });

  String get day => DateFormat('EEEE').format(dateTime);
  String get date => DateFormat('yMMMd').format(dateTime);

  String toString() =>
      '\t{\n\t\t"dayName": "$day",\n\t\t"date": "$date"\n\t}\n';

  Map<String, String> toMap() => {'dayName': day, 'date': date};
}

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

  DateTime start = now;
  DateTime after = now.add(Duration(days: 180));

  DateTime iterator = start;
  List<Day> days = [];

  while (iterator.isBefore(after)) {
    days.add(Day(dateTime: iterator));
    iterator = iterator.add(Duration(days: 1));
  }
  print(days);
}

If you'd like to group the Days by week, we'll then need a multi-dimensional List:

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

  DateTime start = now;
  DateTime after = now.add(Duration(days: 180));

  DateTime iterator = start;
  List<List<Day>> days = [[]]; // multi-dimensional List
  int i = 0;

  while (iterator.isBefore(after)) {
    if (days[i].isEmpty) days.add([]); // init of the week List
    days[i].add(Day(dateTime: iterator));
    if (iterator.weekday == 7) i++;    // new week
    iterator = iterator.add(Duration(days: 1));
  }
  print(days);
}
Share:
2,357
F.SO7
Author by

F.SO7

Updated on December 07, 2022

Comments

  • F.SO7
    F.SO7 11 months

    I am trying to build a weeks-timeline in my Flutter app.

    I am trying to generate a list of all of the weeks in a given time range (for example December 2020 - December 2021).

    Each week will be a list by itself, which will hold the days. Something like this:

    [
        [
            {
                dayName: 'Sunday',
                date: 'December 13 2020',
            },
            {
                dayName: 'Monday',
                date: 'December 14 2020',
            },
            {
                dayName: 'Tuesday',
                date: 'December 15 2020',
            },
            {
                dayName: 'Wednesday',
                date: 'December 16 2020',
            },
            {
                dayName: 'Thursday',
                date: 'December 17 2020',
            },
            {
                dayName: 'Friday',
                date: 'December 18 2020',
            },
            {
                dayName: 'Saturday',
                date: 'December 19 2020',
            },
        ],
        //Another Week Array
        //Another Week Array
        //Etc
    ]
    

    Does anyone know how can I achieve this type of data in Dart and Flutter?

    Thank you!

    • Mohammad Mirshahbazi
      Mohammad Mirshahbazi almost 3 years
      Can you explain more, that what do you want exactly ?
  • F.SO7
    F.SO7 almost 3 years
    Thank you very much. But for some reason your code outputs only 6 items (days) per week. Why isn't it 7?
  • kovalyovi
    kovalyovi almost 3 years
    @F.SO7 thank you for noting! I fixed it and edited my answer. It was a small issue. Does that answer your question?
  • kovalyovi
    kovalyovi almost 3 years
    Hey, @F.SO7, check out my update. I changed it a little since using DayTime for November 01, 2022 creates a bug since there is a transition to the daylight savings. To avoid that instead of using DateTime object I used DateTime.utc. That solved the issue. I also changed hours: 24 to days: 1 for a better clarity.