time.Duration calculation

256 views
Skip to first unread message

Tong Sun

unread,
Dec 24, 2015, 12:40:39 PM12/24/15
to golang-nuts
Is it possible to do calculation on time.Duration? 

A very useful case is, say I get 1/15 of work done in a time.Duration of 20 seconds. I want to get this time.Duration times 15, to extrapolate how long I might be finish in total. 

Is that possible? 
Thanks

Chris Kastorff

unread,
Dec 24, 2015, 12:50:25 PM12/24/15
to Tong Sun, golang-nuts
Sure, just as you'd expect.


You can see in the package documentation that time.Duration is defined as

    type Duration int64

Which means you can do math on them with the builtin operators just like an int64, and you can use any untyped integral constants as time.Duration values (as I did in my example) or convert some integral type you already have (say, an int that you got from len() or whatever) to time.Duration, like time.Duration(value) to use it in a calculation.

Depending on the calculations, you might want to convert everything to float64 and then back again to avoid truncation on integer division and integer overflow problems (though avoid it if you can, it's certainly easier to read without the float conversions.)

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tong Sun

unread,
Dec 24, 2015, 6:18:21 PM12/24/15
to golang-nuts, sunto...@gmail.com
Ah, that's how you get it working. 

Hmm.., could you take a look at this please? 

https://play.golang.org/p/Q2omDalUNZ

The error I got is:

    prog.go:18: invalid operation: time.Since(startTime) * times (mismatched types time.Duration and int64) 

I.e., it only works with constants. If I replace the " * 15 " with a variable, int or int64, it will error out. 

Shall we consider it a bug? 
How can I fix it? 

Thanks

Caleb Spare

unread,
Dec 24, 2015, 6:24:08 PM12/24/15
to Tong Sun, golang-nuts

Jesse McNelis

unread,
Dec 24, 2015, 8:24:04 PM12/24/15
to Tong Sun, golang-nuts


On 25 Dec 2015 10:18 a.m., "Tong Sun" <sunto...@gmail.com> wrote:
>
> I.e., it only works with constants. If I replace the " * 15 " with a variable, int or int64, it will error out. 
>
> Shall we consider it a bug? 
> How can I fix it? 
>

In Go both operands to the multiplication operator need to be of the same type.

You can only multiply a time.Duration by a time.Duration.

The reason is works with untyped constants is that untyped constants gain their type from the context they're used in.

Tong Sun

unread,
Dec 24, 2015, 10:22:15 PM12/24/15
to golang-nuts, sunto...@gmail.com
Thank you Jessta for your further explanation, and Caleb for your code, after which when I read Chris' explanation again, everything make sense to me now. 

But there is still one thing, 

On Thursday, December 24, 2015 at 12:50:25 PM UTC-5, Chris Kastorff wrote:
Sure, just as you'd expect.


You can see in the package documentation that time.Duration is defined as

    type Duration int64

Which means you can do math on them with the builtin operators just like an int64, and you can use any untyped integral constants as time.Duration values (as I did in my example) or convert some integral type you already have (say, an int that you got from len() or whatever) to time.Duration, like time.Duration(value) to use it in a calculation.

Depending on the calculations, you might want to convert everything to float64 and then back again to avoid truncation on integer division and integer overflow problems (though avoid it if you can, it's certainly easier to read without the float conversions.)

Please take a look 

For easy of calculation and understanding, It assumes at *each* step of the loop, the elapsed time is 60 seconds (same), and try to estimate the remaining time. Here is the result I run from my local machine:

Time taken so far 1m0s
Finishing the remaining 80% in 4m0.000008192s
Finishing the remaining 60% in 1m0.000002048s
Finishing the remaining 40% in 0
Finishing the remaining 20% in 0
Finishing the remaining 0% in 0

This is not what I'm expecting. For e.g., when ii==2, two jobs finished in 60 seconds, so the remaining 3 jobs should finish in 60/2*3=90 seconds, not 1m. And for ii==3, I'm expecting 60/3*2=40 seconds, not 0 seconds. 

What I'm doing wrong? 

Thanks

Tong Sun

unread,
Dec 24, 2015, 10:27:00 PM12/24/15
to golang-nuts, sunto...@gmail.com
Oh, I figured out myself. 


On Thursday, December 24, 2015 at 10:22:15 PM UTC-5, Tong Sun wrote:
Thank you Jessta for your further explanation, and Caleb for your code, after which when I read Chris' explanation again, everything make sense to me now. 

But there is still one thing, 

On Thursday, December 24, 2015 at 12:50:25 PM UTC-5, Chris Kastorff wrote:
Sure, just as you'd expect.


You can see in the package documentation that time.Duration is defined as

    type Duration int64

Which means you can do math on them with the builtin operators just like an int64, and you can use any untyped integral constants as time.Duration values (as I did in my example) or convert some integral type you already have (say, an int that you got from len() or whatever) to time.Duration, like time.Duration(value) to use it in a calculation.

Depending on the calculations, you might want to convert everything to float64 and then back again to avoid truncation on integer division and integer overflow problems (though avoid it if you can, it's certainly easier to read without the float conversions.)

Please take a look 

For easy of calculation and understanding, It assumes at *each* step of the loop, the elapsed time is 60 seconds (same), and try to estimate the remaining time. Here is the result I run from my local machine:

Time taken so far 1m0s
Finishing the remaining 80% in 4m0.000008192s
Finishing the remaining 60% in 1m0.000002048s
Finishing the remaining 40% in 0
Finishing the remaining 20% in 0
Finishing the remaining 0% in 0

This is not what I'm expecting. For e.g., when ii==2, two jobs finished in 60 seconds, so the remaining 3 jobs should finish in 60/2*3=90 seconds, not 1m. And for ii==3, I'm expecting 60/3*2=40 seconds, not 0 seconds. 

What I'm doing wrong? 

Do

    time.Duration(int(float32(took)*float32(total-ii)/float32(ii))))

instead of 

     time.Duration(int(float32(took)*float32(1.0*(total-ii)/ii))))

Tong Sun

unread,
Dec 24, 2015, 10:32:26 PM12/24/15
to golang-nuts, sunto...@gmail.com
But how come the code at play.golang 
https://play.golang.org/p/6vs3-RUEgZ
still shows the wrong result (my local run is fine though)?

Time taken so far 1m0s
Finishing the remaining 80% in -2.147483648s
Finishing the remaining 60% in -2.147483648s
Finishing the remaining 40% in -2.147483648s
Finishing the remaining 20% in -2.147483648s
Finishing the remaining 0% in 0

George Burgess IV

unread,
Dec 25, 2015, 2:52:30 AM12/25/15
to golang-nuts, sunto...@gmail.com
Print statements can be helpful when debugging a program: https://play.golang.org/p/FfzK_SOs-7

Tong Sun

unread,
Dec 25, 2015, 9:59:02 AM12/25/15
to Anmol Sethi, golang-nuts
Thank you Anmol. I changed my "float32" to "float64", :-), never occurred to me that it is the 32 bit machines & int64! :-)

On Thu, Dec 24, 2015 at 10:37 PM, Anmol Sethi <an...@aubble.com> wrote:
https://play.golang.org/p/6bVAXzZKco

I believe they are 32 bit machines so you need int64.
Reply all
Reply to author
Forward
0 new messages