Jesse
Jesse

Reputation: 3050

Dart/Flutter How to compare two TimeOfDay times?

TimeOfDay documentation has no comparison operator and primitive comparison does not work. My only solution that I can thinking of right now is to convert TimeOfDay to DateTime and use DateTime's difference method.

Does anyone have a better solution?

Upvotes: 40

Views: 34184

Answers (11)

Falchio
Falchio

Reputation: 616

A small extension for the TimeOfDay class

extension TimeOfDayUtil on TimeOfDay {

  int totalMinutes() {
    return hour * 60 + minute;
  }

  bool isAfter(TimeOfDay other) {
    return totalMinutes() > other.totalMinutes();
  }

  bool isBefore(TimeOfDay other) {
    return totalMinutes() < other.totalMinutes();
  }

  int compareTo(TimeOfDay other) {
    return totalMinutes().compareTo(other.totalMinutes());
  }

}

Upvotes: 0

AshishB
AshishB

Reputation: 817

Solution for negative duration calculations

All these answers are pretty good but they didn't help me when I had a user select a range of times in my app. In order to calculate the total duration of the specified time period, I tried all the solutions which work pretty well but fail in certain scenarios. The scenarios are:

  1. When the start time comes after the end time (i.e- when the duration is supposed to be over 12 hours)
  2. When the start time is before 12am at the night and end time is after that

And the code to overcome it is:

String durationFromTimeOfDay(TimeOfDay? start, TimeOfDay? end) {
    if (start == null || end == null) return '';

    // DateTime(year, month, day, hour, minute)
    final startDT = DateTime(9, 9, 9, start.hour, start.minute);
    final endDT = DateTime(9, 9, 10, end.hour, end.minute);

    final range = DateTimeRange(start: startDT, end: endDT);
    final hours = range.duration.inHours % 24;
    final minutes = range.duration.inMinutes % 60;

    final _onlyHours = minutes == 0;
    final _onlyMinutes = hours == 0;
    final hourText = _onlyMinutes
        ? ''
        : '$hours${_onlyHours ? hours > 1 ? ' hours' : ' hour' : 'h'}';
    final minutesText = _onlyHours
        ? ''
        : '$minutes${_onlyMinutes ? minutes > 1 ? ' mins' : ' min' : 'm'}';
    return hourText + minutesText;
  }

It is important to note that you need to prefill the DateTime for end TimeOfDay with a day value which is greater than the same in start DateTime. The other parameters (for year and month) can be anything you want.

This outputs a really nicely formatted string that is short, concise, and extremely legible enter image description here

This, however, doesn't satisfy the requirement that the solution is devoid of conversion to DateTime. But at least it uses a different approach over the difference method. And this makes the correct duration calculation more reliable in a few lines of code comparatively.

Upvotes: 1

Japsimrans13
Japsimrans13

Reputation: 104

We can actually use the subtract operator.

Code to make magic happen :

Here I wanted to get the difference in time after the user selects the time (in TimeOfDay format) using showTimePicker()

// current time will be used to find the difference between the time selected by the user.
TimeOfDay _cur_time = TimeOfDay(hour: DateTime.now().hour, minute: DateTime.now().minute);

// scheduled time will be updated as soon as the user inputs a new time using the showTimePicker() function available in Flutter Material librabry.
TimeOfDay _scheduled_time = TimeOfDay(hour: DateTime.now().hour, minute: DateTime.now().minute);

// toDouble Function to convert time to double so that we can compare time and check that the time selected is greater than current time.
      double toDouble(TimeOfDay myTime) => myTime.hour + myTime.minute / 60.0;

  void _selectTime() async {
Flutter Material widget to select time.
final TimeOfDay? newTime = await showTimePicker(
  context: context,
  initialTime: _scheduled_time,
);
//Check if the selected time is greater than the cur time
if (toDouble(newTime!) > toDouble(_cur_time)) {
  setState(() {
    _scheduled_time = newTime;
  });
}
  }
Function to get the difference between cur time and selected time.
      Duration _getDelayedDuration(){
        var hourDelay = _scheduled_time.hour - _cur_time.hour;
        print(hourDelay);
        var minuteDelay = _scheduled_time.minute - _cur_time.minute;
        print(minuteDelay);
        return Duration(hours: hourDelay, minutes: minuteDelay);
      }

Upvotes: 0

Shailendra Rajput
Shailendra Rajput

Reputation: 2902

You can use this method. Where you have to provide starttime and endTime in TimesofDay format.

getTime(startTime, endTime) {
  bool result = false;
  int startTimeInt = (startTime.hour * 60 + startTime.minute) * 60;
  int EndTimeInt = (endTime.hour * 60 + endTime.minute) * 60;
  int dif = EndTimeInt - startTimeInt;

  if (EndTimeInt > startTimeInt) {
    result = true;
  } else {
    result = false;
  }
  return result;
}

LikeThis

getTime(v1, v2);

Upvotes: 2

MichaelMitchell
MichaelMitchell

Reputation: 1167

extension TimeOfDayExtension on TimeOfDay {
  int compareTo(TimeOfDay other) {
    if (hour < other.hour) return -1;
    if (hour > other.hour) return 1;
    if (minute < other.minute) return -1;
    if (minute > other.minute) return 1;
    return 0;
  }
}

Upvotes: 19

Zoul Barizi
Zoul Barizi

Reputation: 530

TimeOfDay n = TimeOfDay.now();
int nowSec = (n.hour * 60 + n.minute) * 60;
int veiSec = (t.hour * 60 + t.minute) * 60;
int dif = veiSec - nowSec;

Upvotes: 1

Thanks from @Lucas idea, you can calculate hour and minute by

TimeOfDay yourTime ; 
TimOfDay nowTime = TimeOfDay.now()

double _doubleYourTime = yourTime.hour.toDouble() +
            (yourTime.minute.toDouble() / 60);
double _doubleNowTime = nowTime.hour.toDouble() +
            (nowTime.minute.toDouble() / 60);

double _timeDiff = _doubleYourTime - _doubleNowTime;

double _hr = _timeDiff.truncate();
double _minute = (_timeDiff - _timeDiff.truncate()) * 60;

print('Here your Happy $_hr Hour and also $_minute min');

Upvotes: 9

Kalyan Biswas
Kalyan Biswas

Reputation: 408

Card(
    child: ListTile(
      onTap: () {
        showTimePicker(
          context: context,
          initialTime: TimeOfDay.now(),
        ).then((TimeOfDay time) {
          double _doubleyourTime =
              time.hour.toDouble() + (time.minute.toDouble() /60);
          double _doubleNowTime = TimeOfDay.now().hour.toDouble() +
              (TimeOfDay.now().minute.toDouble() / 60);`enter code here`
          if (_doubleyourTime > _doubleNowTime) {
           print('correct format')
            });
          } else {
           print('Sorry You can not set the time')
         
          }
        });
      },
      //dense: true,
      leading: Icon(Icons.timer),
      title: Text(
        'Today On Time',`enter code here`
      ),
    ),
  ),

Upvotes: 0

matthias_code
matthias_code

Reputation: 1013

I calculated the difference by turning both values into minute-counts, and comparing those :)

TimeOfDay now = TimeOfDay.now();
int nowInMinutes = now.hour * 60 + now.minute;

TimeOfDay testDate = TimeOfDay(hour: 2, minute: 20);
int testDateInMinutes = testDate.hour * 60 + testDate.minute;

Upvotes: 5

Lucas
Lucas

Reputation: 2842

Convert it to a double then compare.

double toDouble(TimeOfDay myTime) => myTime.hour + myTime.minute/60.0

Upvotes: 53

Fellipe Malta
Fellipe Malta

Reputation: 3510

I don't think this is possible. You can use .subtract in DateTime as also .difference

Upvotes: -1

Related Questions