F.SO7
F.SO7

Reputation: 925

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

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!

Upvotes: 1

Views: 3935

Answers (2)

kovalyovi
kovalyovi

Reputation: 1039

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.

Upvotes: 5

Stefano Amorelli
Stefano Amorelli

Reputation: 4854

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);
}

Upvotes: 1

Related Questions