Search code examples
flutterdatetimetimercountdown

Countdown to datetime, stop for a period and after period, count again


On Thurs, Fri, Sat, Sun 6pm-10pm, app allows users certain privileges.

I would like to show the countdown from any date to this period of every Thurs - Sun (6pm-10pm)

Eg If it's Monday, the timer is counting down to Thursday 6pm. If it's Friday 8am, it's counting down to Friday 6pm. At any point of time, the timer should be showing one timing.

And if it's within Thurs - Sun (6pm-10pm), the timer disappears. Only to appear again at Thurs-Sun 22:00:01.

How do I achieve that? Also, for the List of dates, is there a way to make sure the countdown is to every Thurs - Sun (6pm), instead of hard-coding the dates as seen. There's no package used. I'm stuck at the code below.

Following is my truncated code:

List<DateTime> date =
[DateTime.parse("2021-08-26 18:00:00Z"),
DateTime.parse("2021-08-27 18:00:00Z"),
DateTime.parse("2021-08-28 18:00:00Z"),
DateTime.parse("2021-08-29 18:00:00Z"),];

@override 
Widget build(BuildContext context){
return Scaffold(
body: Center(child: ListView.builder(
itemCount: date.length,
itemBuilder: (context, index){
countTime = CountDown().timeLeft(date[0], 'Completed');
return Text(
countTime, 
style(TextStyle(fontSize:25.0));
...

Thank you for your help.

Edited below:

EDITED TO SHOW ADDING OF DAYS IN THE COUNTDOWN error on widget.

truncated code on remainingTimeToText

 String remainingTimeToText(Duration duration) {
    DateTime now = DateTime.now();
    int days = duration.inDays;
    int hours = duration.inHours - days * 24;
    int minutes = duration.inMinutes - hours * 60;
    int seconds = duration.inSeconds - hours * 3600 - minutes * 60;
    if (now.weekday < 4) {
      return days.toString() +
          ' days ' +
          hours.toString() +
          ":" +
          minutes.toString() +
          ":" +
          seconds.toString();
    } else if (now.weekday>3){return 
        hours.toString() +
        ":" +
        minutes.toString() +
        ":" +
        seconds.toString();
  }

Solution

  • import 'package:flutter/material.dart';
    
    //needed for using the Timer
    import 'dart:async';
    
    class TimerScreen extends StatefulWidget {
      const TimerScreen({Key? key}) : super(key: key);
    
      @override
      _TimerScreenState createState() => _TimerScreenState();
    }
    
    class _TimerScreenState extends State<TimerScreen> {
    //the time left till the next special time comes up
      String timeLeft = "";
    
      ///takes an int when converting it to string adds
      /// a 0 in fron when it is smaller than 10
      ///
      ///will look nicer  when displayed on the screen
      String customString(int i) {
        if (i < 10) {
          return "0" + i.toString();
        } else {
          return i.toString();
        }
      }
    
      ///converts a duration to a
      ///string: days hours:minuts:seconds
      String remainingTimeToText(Duration duration) {
        print(duration);
        int days = duration.inDays;
        int hours = duration.inHours - days * 24;
        int minutes = duration.inMinutes - hours * 60 - days * 24 * 60;
        int seconds =
            duration.inSeconds - hours * 3600 - minutes * 60 - days * 86400;
        if (days > 0) {
          String s = " days ";
          if (days == 1) {
            s = " day ";
          }
          return days.toString() +
              s +
              customString(hours) +
              ":" +
              customString(minutes) +
              ":" +
              customString(seconds);
        } else {
          return customString(hours) +
              ":" +
              customString(minutes) +
              ":" +
              customString(seconds);
        }
      }
    
      ///given a list of ints and another int value
      ///
      ///returs true it the value is contained in the list
      ///
      ///else returns false
      bool listContainsValue(List<int> list, int value) {
        for (var element in list) {
          if (element == value) {
            print(true);
            return true;
          }
        }
        print(false);
        return false;
      }
    
      ///returns the time remaining till the next
      ///special time takes place as a string: hours:minutes:seconds
      ///
      ///if specialTime is currently active
      ///it returns an empty string
      ///
      ///specialTimes have to be given by entering an int list with all special
      ///weekdays and entering the startingHour and the endingHour
      timeRemaining(List<int> weekdays, int startingHour, int endingHour) {
        DateTime now = DateTime.now();
        bool timeIsSpecial = false;
        for (var specificWeekday in weekdays) {
          if (now.weekday == specificWeekday &&
              (now.hour >= startingHour && now.hour < endingHour)) {
            timeIsSpecial = true;
          }
        }
        print(timeIsSpecial);
        if (!timeIsSpecial) {
          DateTime nextSpecialTime =
              DateTime(now.year, now.month, now.day, startingHour);
          while (nextSpecialTime.isBefore(now) ||
              !listContainsValue(weekdays, nextSpecialTime.weekday)) {
            nextSpecialTime = nextSpecialTime.add(Duration(days: 1));
          }
          return remainingTimeToText(nextSpecialTime.difference(now));
        } else {
          return "";
        }
      }
    
      @override
      void initState() {
        Timer.periodic(Duration(seconds: 1), (timer) {
          if (mounted == true) {
            setState(() {
              timeLeft = timeRemaining([4, 5, 6], 18, 22);
            });
          }
        });
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          body: Container(
            child: Center(
              child: Text(
                timeLeft,
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 40,
                ),
              ),
            ),
          ),
        );
      }
    }