calculate hours/minutes between two times in dart - flutter

I want to get/calculate hours and minutes between two times in dart.
Example: if start_time is 17:30 and end_time is 09:00 (day after) it should return total: 15 hours 30 minutes
My code:
check_two_times_is_before(String start_time, String end_time){
var format = DateFormat("HH:mm");
var start = format.parse(start_time);
var end = format.parse(end_time);
if(start.isAfter(end)) {
// do something here
}
}

You can use difference method on DateTime class.
check_two_times_is_before(String start_time, String end_time){
var format = DateFormat("HH:mm");
var start = format.parse(start_time);
var end = format.parse(end_time);
if(start.isAfter(end)) {
end = end.add(Duration(days: 1));
Duration diff = end.difference(start);
final hours = diff.inHours;
final minutes = diff.inMinutes % 60;
print('$hours hours $minutes minutes');
}
}

You can try it with Duration class
Duration duration = end.difference(start).abs();
final hours = duration.inHours;
final minutes = duration.inMinutes % 60;
print('$hours hours $minutes minutes');

The question is pretty old but here is another solution which might help someone.
Duration duration = DateTime.fromMillisecondsSinceEpoch(timestmap).difference(DateTime.now()).abs();
final days = duration.inDays;
final hours = duration.inHours - (days * 24);
final minutes = duration.inMinutes - (days * 24 * 60) - (hours * 60);
final seconds = duration.inSeconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);
Nothing to explain here really. We're just using basic algebra. We're getting the total number of milliseconds between the two timestamps and working that down to days, hours, minutes and seconds.

Related

Dart | Convert seconds to DateTime without calculate

Sometimes we need day, hour, minute, second to countdown, but what we know just second.
For example:
1s -> 0day 0hour 0minute 1s
10s -> 0day 0hour 0minute 10s
100s -> 0day 0hour 1minute 40s
Here is my solution:
void _test() {
var diffseconds = 100;
var seconds = diffseconds % 60;
var minute = diffseconds ~/ 60 % 60;
var hour = diffseconds ~/ 60 ~/ 60 % 24;
var day = diffseconds ~/ 60 ~/ 60 ~/ 24;
print('day=$day');
print('hour=$hour');
print('minute=$minute');
print('second=$seconds');
}
If I can change second to DateTime, I can get day easily with date.day and so on and I don't need to calculate anymore.
So I wonder is there any api or simple way to achieve it without any calculate.
I wonder better solution.
I don't think this functionality is built into Dart but you can somewhat easy add the following extension to Duration which are more or less what you are already are doing:
extension RestTimeOnDuration on Duration {
int get inDaysRest => inDays;
int get inHoursRest => inHours - (inDays * 24);
int get inMinutesRest => inMinutes - (inHours * 60);
int get inSecondsRest => inSeconds - (inMinutes * 60);
int get inMillisecondsRest => inMilliseconds - (inSeconds * 1000);
int get inMicrosecondsRest => inMicroseconds - (inMilliseconds * 1000);
}
void main() {
const duration = Duration(seconds: 123);
print('Days: ${duration.inDaysRest}'); // 0
print('Hours: ${duration.inHoursRest}'); // 0
print('Minutes: ${duration.inMinutesRest}'); // 2
print('Seconds: ${duration.inSecondsRest}'); // 3
print('Milliseconds: ${duration.inMillisecondsRest}'); // 0
print('Microseconds: ${duration.inMicrosecondsRest}'); // 0
}
Just use Duration(seconds: seconds), it handles values more than 60.
Duration(seconds: 123) // 2 minutes and 3 seconds

how to create a 30 minutes timeslot.. Im getting the start date and end date from backend

List<WorkingHourModel> workingHours = response['hours'];
int startTime = int.parse(workingHours[0].startTime.split(':')[0]);
int endTime = int.parse(workingHours[0].endTime.split(':')[0]);
int hoursLeft = endTime - startTime + 1;
List<String> hours =
List.generate(hoursLeft, (i) => '${(endTime - i)}:00').reversed
.toList();
print('Hours-------- $hours');
return {
'success': true,
'hours': hours,
};
}
//this will give the time slots as '1:00', '2:00', '3:00', '4:00'
//Start time will be 1:00 and end time will be 4:00.
Heading
But i need 30 mins breakage, like,
'1:00', '1:30', '2:00', '2:30', '3:00', '3:30', '4:00'
Kindly help..
This should generate the list as you want it:
void main(List<String> args) {
// lets assume 9 to 5
int startTime = 9;
int endTime = 17;
int hoursLeft = endTime - startTime + 1;
final hours = List.generate(hoursLeft * 2, (i) => '${endTime - (i/2).truncate()}:${i%2 == 1 ? '00' : '30'}').reversed.toList();
print('Hours-------- $hours');
}
Hours-------- [9:00, 9:30, 10:00, 10:30, 11:00, 11:30, 12:00, 12:30, 13:00, 13:30, 14:00, 14:30, 15:00, 15:30, 16:00, 16:30, 17:00, 17:30]
Generally speaking, if you have more complicated calculations (what happens if someone works 18:00 to 05:00 in the nightshift?) you may want to use the proper datatypes instead of integers and string concatenation.

How to convert the time to minutes of Timer

I have this time that starts when a product is initialized and I want to format it to 00:00 instead of just 0.
Timer _timer;
_startTimer(prod) {
prod.tempo = 0;
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
prod.tempo++;
});
});
}`
[you can se the time in red I want to convert][1]
[1]: https://i.stack.imgur.com/vCv7p.jpg
If you have a total number of seconds, you can pretty print it with:
String toTimeField(int n) => n.toString().padLeft(2, '0');
var seconds = totalSeconds % 60;
var minutes = totalSeconds ~/ 60;
var prettyDuration = '${toTimeField(minutes)}:${toTimeField(seconds)}`;
That said, if you want to measure a duration, you're usually better off keeping track of the starting time and then computing the difference with the current time. That prevents accumulating error if there are any timing discrepancies from when your callback fires. You can use DateTime.now() to get the current time, store it, and then when your callback fires, call DateTime.now() again and subtract the original value. Or use the Stopwatch class, which does that for you. Using Stopwatch and Duration, you'd do:
_startTimer(prod) {
prod.stopwatch = Stopwatch();
...
}
...
final elapsed = prod.stopwatch.elapsed;
var seconds = elapsed.inSeconds % 60;
var minutes = elapsed.inMinutes;
Finally, I also recommend avoiding using : when printing durations since it could easily be misinterpreted. Does 12:34 represent a time? Does it represent 12 hours and 34 minutes or 12 minutes and 34 seconds? Printing durations as 12m34s is much clearer.
You can format the String as follows:
var seconds = prod.tempo % 60;
var minutes = (prod.tempo - seconds) / 60;
//if you have less than 10 seconds/minutes, prepend a '0':
String secondsAsString = seconds < 10 ? '0$seconds' : seconds;
String minutesAsString = minutes < 10 ? '0$minutes' : minutes;
String displayTime = 'Tempo: ' + secondsAsString + ':' + minutesAsString;

MInutes and seconds with 2 digits

I have an input in seconds I store it in a var:
var totalTime = 60
I want to show it with 2 digits for minutes and 2 digits for seconds:
01:00
What I have tried:
let minutes = String(totalTime / 60)
let seconds = String(totalTime % 60)
label.text = minutes + ":" + seconds
This gives me: 1:0
But I want 01:00
I tried and It does not work:
label.text = String(format: "%02d:%02d", minutes, seconds)
The problem with your second approach is that it expects an integer and you are passing a string.
let minutes = totalTime / 60
let seconds = totalTime % 60
label.text = String(format: "%02d:%02d", minutes, seconds)

How to convert milliseconds into human readable form?

I need to convert an arbitrary amount of milliseconds into Days, Hours, Minutes Second.
For example: 10 Days, 5 hours, 13 minutes, 1 second.
Well, since nobody else has stepped up, I'll write the easy code to do this:
x = ms / 1000
seconds = x % 60
x /= 60
minutes = x % 60
x /= 60
hours = x % 24
x /= 24
days = x
I'm just glad you stopped at days and didn't ask for months. :)
Note that in the above, it is assumed that / represents truncating integer division. If you use this code in a language where / represents floating point division, you will need to manually truncate the results of the division as needed.
Let A be the amount of milliseconds. Then you have:
seconds=(A/1000)%60
minutes=(A/(1000*60))%60
hours=(A/(1000*60*60))%24
and so on (% is the modulus operator).
Hope this helps.
Both solutions below use javascript (I had no idea the solution was language agnostic!). Both solutions will need to be extended if capturing durations > 1 month.
Solution 1: Use the Date object
var date = new Date(536643021);
var str = '';
str += date.getUTCDate()-1 + " days, ";
str += date.getUTCHours() + " hours, ";
str += date.getUTCMinutes() + " minutes, ";
str += date.getUTCSeconds() + " seconds, ";
str += date.getUTCMilliseconds() + " millis";
console.log(str);
Gives:
"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"
Libraries are helpful, but why use a library when you can re-invent the wheel! :)
Solution 2: Write your own parser
var getDuration = function(millis){
var dur = {};
var units = [
{label:"millis", mod:1000},
{label:"seconds", mod:60},
{label:"minutes", mod:60},
{label:"hours", mod:24},
{label:"days", mod:31}
];
// calculate the individual unit values...
units.forEach(function(u){
millis = (millis - (dur[u.label] = (millis % u.mod))) / u.mod;
});
// convert object to a string representation...
var nonZero = function(u){ return dur[u.label]; };
dur.toString = function(){
return units
.reverse()
.filter(nonZero)
.map(function(u){
return dur[u.label] + " " + (dur[u.label]==1?u.label.slice(0,-1):u.label);
})
.join(', ');
};
return dur;
};
Creates a "duration" object, with whatever fields you require.
Formatting a timestamp then becomes simple...
console.log(getDuration(536643021).toString());
Gives:
"6 days, 5 hours, 4 minutes, 3 seconds, 21 millis"
Apache Commons Lang has a DurationFormatUtils that has very helpful methods like formatDurationWords.
You should use the datetime functions of whatever language you're using, but, just for fun here's the code:
int milliseconds = someNumber;
int seconds = milliseconds / 1000;
int minutes = seconds / 60;
seconds %= 60;
int hours = minutes / 60;
minutes %= 60;
int days = hours / 24;
hours %= 24;
This is a method I wrote. It takes an integer milliseconds value and returns a human-readable String:
public String convertMS(int ms) {
int seconds = (int) ((ms / 1000) % 60);
int minutes = (int) (((ms / 1000) / 60) % 60);
int hours = (int) ((((ms / 1000) / 60) / 60) % 24);
String sec, min, hrs;
if(seconds<10) sec="0"+seconds;
else sec= ""+seconds;
if(minutes<10) min="0"+minutes;
else min= ""+minutes;
if(hours<10) hrs="0"+hours;
else hrs= ""+hours;
if(hours == 0) return min+":"+sec;
else return hrs+":"+min+":"+sec;
}
function convertTime(time) {
var millis= time % 1000;
time = parseInt(time/1000);
var seconds = time % 60;
time = parseInt(time/60);
var minutes = time % 60;
time = parseInt(time/60);
var hours = time % 24;
var out = "";
if(hours && hours > 0) out += hours + " " + ((hours == 1)?"hr":"hrs") + " ";
if(minutes && minutes > 0) out += minutes + " " + ((minutes == 1)?"min":"mins") + " ";
if(seconds && seconds > 0) out += seconds + " " + ((seconds == 1)?"sec":"secs") + " ";
if(millis&& millis> 0) out += millis+ " " + ((millis== 1)?"msec":"msecs") + " ";
return out.trim();
}
In java
public static String formatMs(long millis) {
long hours = TimeUnit.MILLISECONDS.toHours(millis);
long mins = TimeUnit.MILLISECONDS.toMinutes(millis);
long secs = TimeUnit.MILLISECONDS.toSeconds(millis);
return String.format("%dh %d min, %d sec",
hours,
mins - TimeUnit.HOURS.toMinutes(hours),
secs - TimeUnit.MINUTES.toSeconds(mins)
);
}
Gives something like this:
12h 1 min, 34 sec
I would suggest using whatever date/time functions/libraries your language/framework of choice provides. Also check out string formatting functions as they often provide easy ways to pass date/timestamps and output a human readable string format.
Your choices are simple:
Write the code to do the conversion (ie, divide by milliSecondsPerDay to get days and use the modulus to divide by milliSecondsPerHour to get hours and use the modulus to divide by milliSecondsPerMinute and divide by 1000 for seconds. milliSecondsPerMinute = 60000, milliSecondsPerHour = 60 * milliSecondsPerMinute, milliSecondsPerDay = 24 * milliSecondsPerHour.
Use an operating routine of some kind. UNIX and Windows both have structures that you can get from a Ticks or seconds type value.
Long serverUptimeSeconds =
(System.currentTimeMillis() - SINCE_TIME_IN_MILLISECONDS) / 1000;
String serverUptimeText =
String.format("%d days %d hours %d minutes %d seconds",
serverUptimeSeconds / 86400,
( serverUptimeSeconds % 86400) / 3600 ,
((serverUptimeSeconds % 86400) % 3600 ) / 60,
((serverUptimeSeconds % 86400) % 3600 ) % 60
);
Why just don't do something like this:
var ms = 86400;
var seconds = ms / 1000; //86.4
var minutes = seconds / 60; //1.4400000000000002
var hours = minutes / 60; //0.024000000000000004
var days = hours / 24; //0.0010000000000000002
And dealing with float precision e.g. Number(minutes.toFixed(5)) //1.44
I'm not able to comment first answer to your question, but there's a small mistake. You should use parseInt or Math.floor to convert floating point numbers to integer, i
var days, hours, minutes, seconds, x;
x = ms / 1000;
seconds = Math.floor(x % 60);
x /= 60;
minutes = Math.floor(x % 60);
x /= 60;
hours = Math.floor(x % 24);
x /= 24;
days = Math.floor(x);
Personally, I use CoffeeScript in my projects and my code looks like that:
getFormattedTime : (ms)->
x = ms / 1000
seconds = Math.floor x % 60
x /= 60
minutes = Math.floor x % 60
x /= 60
hours = Math.floor x % 24
x /= 24
days = Math.floor x
formattedTime = "#{seconds}s"
if minutes then formattedTime = "#{minutes}m " + formattedTime
if hours then formattedTime = "#{hours}h " + formattedTime
formattedTime
This is a solution. Later you can split by ":" and take the values of the array
/**
* Converts milliseconds to human readeable language separated by ":"
* Example: 190980000 --> 2:05:3 --> 2days 5hours 3min
*/
function dhm(t){
var cd = 24 * 60 * 60 * 1000,
ch = 60 * 60 * 1000,
d = Math.floor(t / cd),
h = '0' + Math.floor( (t - d * cd) / ch),
m = '0' + Math.round( (t - d * cd - h * ch) / 60000);
return [d, h.substr(-2), m.substr(-2)].join(':');
}
var delay = 190980000;
var fullTime = dhm(delay);
console.log(fullTime);
Long expireTime = 69l;
Long tempParam = 0l;
Long seconds = math.mod(expireTime, 60);
tempParam = expireTime - seconds;
expireTime = tempParam/60;
Long minutes = math.mod(expireTime, 60);
tempParam = expireTime - minutes;
expireTime = expireTime/60;
Long hours = math.mod(expireTime, 24);
tempParam = expireTime - hours;
expireTime = expireTime/24;
Long days = math.mod(expireTime, 30);
system.debug(days + '.' + hours + ':' + minutes + ':' + seconds);
This should print: 0.0:1:9
Here's my solution using TimeUnit.
UPDATE: I should point out that this is written in groovy, but Java is almost identical.
def remainingStr = ""
/* Days */
int days = MILLISECONDS.toDays(remainingTime) as int
remainingStr += (days == 1) ? '1 Day : ' : "${days} Days : "
remainingTime -= DAYS.toMillis(days)
/* Hours */
int hours = MILLISECONDS.toHours(remainingTime) as int
remainingStr += (hours == 1) ? '1 Hour : ' : "${hours} Hours : "
remainingTime -= HOURS.toMillis(hours)
/* Minutes */
int minutes = MILLISECONDS.toMinutes(remainingTime) as int
remainingStr += (minutes == 1) ? '1 Minute : ' : "${minutes} Minutes : "
remainingTime -= MINUTES.toMillis(minutes)
/* Seconds */
int seconds = MILLISECONDS.toSeconds(remainingTime) as int
remainingStr += (seconds == 1) ? '1 Second' : "${seconds} Seconds"
A flexible way to do it :
(Not made for current date but good enough for durations)
/**
convert duration to a ms/sec/min/hour/day/week array
#param {int} msTime : time in milliseconds
#param {bool} fillEmpty(optional) : fill array values even when they are 0.
#param {string[]} suffixes(optional) : add suffixes to returned values.
values are filled with missings '0'
#return {int[]/string[]} : time values from higher to lower(ms) range.
*/
var msToTimeList=function(msTime,fillEmpty,suffixes){
suffixes=(suffixes instanceof Array)?suffixes:[]; //suffixes is optional
var timeSteps=[1000,60,60,24,7]; // time ranges : ms/sec/min/hour/day/week
timeSteps.push(1000000); //add very big time at the end to stop cutting
var result=[];
for(var i=0;(msTime>0||i<1||fillEmpty)&&i<timeSteps.length;i++){
var timerange = msTime%timeSteps[i];
if(typeof(suffixes[i])=="string"){
timerange+=suffixes[i]; // add suffix (converting )
// and fill zeros :
while( i<timeSteps.length-1 &&
timerange.length<((timeSteps[i]-1)+suffixes[i]).length )
timerange="0"+timerange;
}
result.unshift(timerange); // stack time range from higher to lower
msTime = Math.floor(msTime/timeSteps[i]);
}
return result;
};
NB : you could also set timeSteps as parameter if you want to control the time ranges.
how to use (copy an test):
var elsapsed = Math.floor(Math.random()*3000000000);
console.log( "elsapsed (labels) = "+
msToTimeList(elsapsed,false,["ms","sec","min","h","days","weeks"]).join("/") );
console.log( "half hour : "+msToTimeList(elsapsed,true)[3]<30?"first":"second" );
console.log( "elsapsed (classic) = "+
msToTimeList(elsapsed,false,["","","","","",""]).join(" : ") );
I suggest to use http://www.ocpsoft.org/prettytime/ library..
it's very simple to get time interval in human readable form like
PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
it will print like "moments from now"
other example
PrettyTime p = new PrettyTime());
Date d = new Date(System.currentTimeMillis());
d.setHours(d.getHours() - 1);
String ago = p.format(d);
then string ago = "1 hour ago"
In python 3 you could achieve your goal by using the following snippet:
from datetime import timedelta
ms = 536643021
td = timedelta(milliseconds=ms)
print(str(td))
# --> 6 days, 5:04:03.021000
Timedelta documentation: https://docs.python.org/3/library/datetime.html#datetime.timedelta
Source of the __str__ method of timedelta str: https://github.com/python/cpython/blob/33922cb0aa0c81ebff91ab4e938a58dfec2acf19/Lib/datetime.py#L607
Here is more precise method in JAVA , I have implemented this simple logic , hope this will help you:
public String getDuration(String _currentTimemilliSecond)
{
long _currentTimeMiles = 1;
int x = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;
int month = 0;
int year = 0;
try
{
_currentTimeMiles = Long.parseLong(_currentTimemilliSecond);
/** x in seconds **/
x = (int) (_currentTimeMiles / 1000) ;
seconds = x ;
if(seconds >59)
{
minutes = seconds/60 ;
if(minutes > 59)
{
hours = minutes/60;
if(hours > 23)
{
days = hours/24 ;
if(days > 30)
{
month = days/30;
if(month > 11)
{
year = month/12;
Log.d("Year", year);
Log.d("Month", month%12);
Log.d("Days", days % 30);
Log.d("hours ", hours % 24);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds ", seconds % 60);
return "Year "+year + " Month "+month%12 +" Days " +days%30 +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
}
else
{
Log.d("Month", month);
Log.d("Days", days % 30);
Log.d("hours ", hours % 24);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds ", seconds % 60);
return "Month "+month +" Days " +days%30 +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
}
}
else
{
Log.d("Days", days );
Log.d("hours ", hours % 24);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds ", seconds % 60);
return "Days " +days +" hours "+hours%24 +" Minutes "+minutes %60+" Seconds "+seconds%60;
}
}
else
{
Log.d("hours ", hours);
Log.d("Minutes ", minutes % 60);
Log.d("Seconds ", seconds % 60);
return "hours "+hours+" Minutes "+minutes %60+" Seconds "+seconds%60;
}
}
else
{
Log.d("Minutes ", minutes);
Log.d("Seconds ", seconds % 60);
return "Minutes "+minutes +" Seconds "+seconds%60;
}
}
else
{
Log.d("Seconds ", x);
return " Seconds "+seconds;
}
}
catch (Exception e)
{
Log.e(getClass().getName().toString(), e.toString());
}
return "";
}
private Class Log
{
public static void d(String tag , int value)
{
System.out.println("##### [ Debug ] ## "+tag +" :: "+value);
}
}
A solution using awk:
$ ms=10000001; awk -v ms=$ms 'BEGIN {x=ms/1000;
s=x%60; x/=60;
m=x%60; x/=60;
h=x%60;
printf("%02d:%02d:%02d.%03d\n", h, m, s, ms%1000)}'
02:46:40.001
This one leaves out 0 values. With tests.
const toTimeString = (value, singularName) =>
`${value} ${singularName}${value !== 1 ? 's' : ''}`;
const readableTime = (ms) => {
const days = Math.floor(ms / (24 * 60 * 60 * 1000));
const daysMs = ms % (24 * 60 * 60 * 1000);
const hours = Math.floor(daysMs / (60 * 60 * 1000));
const hoursMs = ms % (60 * 60 * 1000);
const minutes = Math.floor(hoursMs / (60 * 1000));
const minutesMs = ms % (60 * 1000);
const seconds = Math.round(minutesMs / 1000);
const data = [
[days, 'day'],
[hours, 'hour'],
[minutes, 'minute'],
[seconds, 'second'],
];
return data
.filter(([value]) => value > 0)
.map(([value, name]) => toTimeString(value, name))
.join(', ');
};
// Tests
const hundredDaysTwentyHoursFiftyMinutesThirtySeconds = 8715030000;
const oneDayTwoHoursEightMinutesTwelveSeconds = 94092000;
const twoHoursFiftyMinutes = 10200000;
const oneMinute = 60000;
const fortySeconds = 40000;
const oneSecond = 1000;
const oneDayTwelveSeconds = 86412000;
const test = (result, expected) => {
console.log(expected, '- ' + (result === expected));
};
test(readableTime(
hundredDaysTwentyHoursFiftyMinutesThirtySeconds
), '100 days, 20 hours, 50 minutes, 30 seconds');
test(readableTime(
oneDayTwoHoursEightMinutesTwelveSeconds
), '1 day, 2 hours, 8 minutes, 12 seconds');
test(readableTime(
twoHoursFiftyMinutes
), '2 hours, 50 minutes');
test(readableTime(
oneMinute
), '1 minute');
test(readableTime(
fortySeconds
), '40 seconds');
test(readableTime(
oneSecond
), '1 second');
test(readableTime(
oneDayTwelveSeconds
), '1 day, 12 seconds');