Trying to obtain successive timestamps with below Go code
package main
import "fmt"
import "time"
func main () {
ts := int64(1500000000) // start
for i := int64(0); i<1e6; i = i + 1000 { // successively add 1e3
t := time.Unix(ts, i) // Get start + i
fmt.Printf("%d %02d:%02d\n", ts+i, t.Hour(), t.Minute())
}
}
, output remains like
....
1500995000 04:40
1500996000 04:40
1500997000 04:40
1500998000 04:40
1500999000 04:40
Please, what is the problem here ? Why the hour:minute doesn't vary ? (04:40)
go version go1.15.6 linux/amd64
You are changing the nanoseconds and printing minutes...
https://pkg.go.dev/time#go1.16.7#Unix
func Unix(sec int64, nsec int64) Time
Check this:
https://play.golang.org/p/_Ywn9S5Khch
package main
import "fmt"
import "time"
func main () {
ts := int64(1500000000) // start
for i := int64(0); i<1e6; i = i + 1000 { // successively add 1e3
t := time.Unix(ts, i) // Get start + i
fmt.Printf("%d %02d:%02d ---- %2d\n", ts+i, t.Hour(), t.Minute(), t.UnixNano())
}
}
Related
I would like to build a program which runs a number of cron jobs which start at a time which, in general, is in the past. Here is a simplified example using gocron:
package main
import (
"time"
"github.com/jasonlvhit/gocron"
"github.com/sirupsen/logrus"
)
// This slice would be obtained from persistent storage
var startTimes = []time.Time{
time.Now().Add(-4 * time.Second),
time.Now().Add(-3 * time.Second),
}
func format(t time.Time) string {
return t.Format("15:04:05")
}
func notify(startTime time.Time) {
logrus.WithField("time", format(time.Now())).Infof("I started at %s\n", format(startTime))
}
func main() {
for _, startTime := range startTimes {
gocron.Every(10).Seconds().From(&startTime).Do(notify, startTime)
}
logrus.Infof("Starting at %s...\n", format(time.Now()))
<-gocron.Start()
}
If I run this, I get the following output:
INFO[0000] Starting at 00:30:54...
INFO[0010] I started at 00:30:50 fields.time="00:31:04"
INFO[0010] I started at 00:30:51 fields.time="00:31:04"
What I observe is that all the events are happening at once, 10 seconds after I start the program.
However, since the startTimes are 4 and 3 seconds before the program starts, what I would like is for the events to occur 6 and 7 seconds after the program starts (and every 10 seconds after that), respectively.
Is there a way to do this with gocron or some other tool?
This seems like just simple math:
interval := 10 * time.Second
nextTime := time.Now().Add((time.Since(startTime) + interval) % interval)
gocron.Every(10).Seconds().From(&nextTime).Do(notify, nextTime)
https://play.golang.org/p/pwEZqy_LUuk
We can try to leverage a simple ticker, it is not a complete solution but should be easy enough to adapt.
package main
import (
"fmt"
"time"
)
func ticker(period time.Duration, length ...time.Duration) <-chan time.Time {
ticker := time.NewTicker(period)
if len(length) > 0 {
done := make(chan bool)
go func() {
time.Sleep(period + length[0])
done <- true
}()
go func() {
<-done
ticker.Stop()
}()
}
return ticker.C
}
func main() {
t1 := ticker(6*time.Second, 4*time.Second)
t2 := ticker(7*time.Second, 3*time.Second)
t3 := ticker(10 * time.Second)
for {
select {
case t1 := <-t1:
fmt.Println("t1: ", t1)
case t2 := <-t2:
fmt.Println("t2: ", t2)
case t3 := <-t3:
fmt.Println("t3: ", t3)
}
}
}
I am attempting to clock the execution of a process and I need the value in seconds.
package main
import (
"fmt"
"time"
)
func main() {
startTime := time.Now()
time.Sleep(1379 * time.Millisecond)
elapsedTime := time.Since(startTime)
fmt.Println(elapsedTime) //->1.379s
secs := float64(elapsedTime / time.Second)
fmt.Println(secs)//->1
//desired output is: 1.379
}
I am looking for a way to have the time not NOT being rounded.
Here's the playground: https://play.golang.org/p/VLgKTpmkHPS
Just use the Seconds() method:
package main
import (
"fmt"
"time"
)
func main() {
elapsedTime := 1379 * time.Millisecond
fmt.Println(elapsedTime) //->1.379s
secs := elapsedTime.Seconds()
fmt.Println(secs)
}
playground.
Epoc time to to convert the time to seconds
update : Below code works ?
package main
import (
"fmt"
"time"
)
func main() {
startTime := time.Now()
nanos := startTime.Unix()
// fmt.Println(startTime)
millis := nanos / 1000000
elapsedInsecondsT := float64(millis)/float64(1000)
fmt.Println( millis, elapsedInsecondsT )
}
courtesy : https://gobyexample.com/epoch
In python I can see how many seconds have elapsed during a specific process like,
started = time.time()
doProcess()
print(time.time()-started)
Whats the equivelent in golang?
import (
"fmt"
"time"
)
func main() {
begin := time.Now()
time.Sleep(10 * time.Millisecond)
end := time.Now()
duration := end.Sub(begin)
fmt.Println(duration)
}
import (
"fmt"
"time"
)
func main() {
started := time.Now()
doProcess()
fmt.Println(time.Now().Sub(started).Seconds())
}
Package time
func Since
func Since(t Time) Duration
Since returns the time elapsed since t. It is shorthand for
time.Now().Sub(t).
Your Python example in Go:
package main
import (
"fmt"
"time"
)
func main() {
started := time.Now()
time.Sleep(1 * time.Second)
fmt.Println(time.Since(started))
}
Output:
1s
Is there a way to scan a big.Int directly from the standard input in Go? Right now I'm doing this:
package main
import (
"fmt"
"math/big"
)
func main() {
w := new(big.Int)
var s string
fmt.Scan(&s)
fmt.Sscan(s, w)
fmt.Println(w)
}
I also could have used .SetString. But, is there a way to Scan the big.Int directly from the standard input without scanning a string or an integer first?
For example,
package main
import (
"fmt"
"math/big"
)
func main() {
w := new(big.Int)
n, err := fmt.Scan(w)
fmt.Println(n, err)
fmt.Println(w.String())
}
Input (stdin):
295147905179352825857
Output (stdout):
1 <nil>
295147905179352825857
As far as I know - no, there's no other way. In fact, what you've got is the default example they have for scanning big.Int in the documentation.
package main
import (
"fmt"
"log"
"math/big"
)
func main() {
// The Scan function is rarely used directly;
// the fmt package recognizes it as an implementation of fmt.Scanner.
i := new(big.Int)
_, err := fmt.Sscan("18446744073709551617", i)
if err != nil {
log.Println("error scanning value:", err)
} else {
fmt.Println(i)
}
}
You can see the relevant section here - http://golang.org/pkg/math/big/#Int.Scan
I have been looking around for examples on how to implement a function that allows you to execute tasks at a certain time in Go, but I couldn't find anything.
I implemented one myself and I am sharing it in the answers, so other people can have a reference for their own implementation.
This is a general implementation, which lets you set:
interval period
hour to tick
minute to tick
second to tick
UPDATED: (the memory leak was fixed)
import (
"fmt"
"time"
)
const INTERVAL_PERIOD time.Duration = 24 * time.Hour
const HOUR_TO_TICK int = 23
const MINUTE_TO_TICK int = 00
const SECOND_TO_TICK int = 03
type jobTicker struct {
timer *time.Timer
}
func runningRoutine() {
jobTicker := &jobTicker{}
jobTicker.updateTimer()
for {
<-jobTicker.timer.C
fmt.Println(time.Now(), "- just ticked")
jobTicker.updateTimer()
}
}
func (t *jobTicker) updateTimer() {
nextTick := time.Date(time.Now().Year(), time.Now().Month(),
time.Now().Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
if !nextTick.After(time.Now()) {
nextTick = nextTick.Add(INTERVAL_PERIOD)
}
fmt.Println(nextTick, "- next tick")
diff := nextTick.Sub(time.Now())
if t.timer == nil {
t.timer = time.NewTimer(diff)
} else {
t.timer.Reset(diff)
}
}
In case someone drops in on this question searching for a quick solution.
I found a neat library that makes it really easy to schedule jobs.
Link: https://github.com/jasonlvhit/gocron
The API is pretty straightforward:
import (
"fmt"
"github.com/jasonlvhit/gocron"
)
func task() {
fmt.Println("Task is being performed.")
}
func main() {
s := gocron.NewScheduler()
s.Every(2).Hours().Do(task)
<- s.Start()
}
the answer provided by #Daniele B is not good enough, as #Caleb says, that implementation leaks memory, because each time we create a new ticker, the old one will never be released.
so I wrap the time.timer, and reset it everytime, a example here:
package main
import (
"fmt"
"time"
)
const INTERVAL_PERIOD time.Duration = 24 * time.Hour
const HOUR_TO_TICK int = 23
const MINUTE_TO_TICK int = 21
const SECOND_TO_TICK int = 03
type jobTicker struct {
t *time.Timer
}
func getNextTickDuration() time.Duration {
now := time.Now()
nextTick := time.Date(now.Year(), now.Month(), now.Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
if nextTick.Before(now) {
nextTick = nextTick.Add(INTERVAL_PERIOD)
}
return nextTick.Sub(time.Now())
}
func NewJobTicker() jobTicker {
fmt.Println("new tick here")
return jobTicker{time.NewTimer(getNextTickDuration())}
}
func (jt jobTicker) updateJobTicker() {
fmt.Println("next tick here")
jt.t.Reset(getNextTickDuration())
}
func main() {
jt := NewJobTicker()
for {
<-jt.t.C
fmt.Println(time.Now(), "- just ticked")
jt.updateJobTicker()
}
}
I have created a package that actually supports crontab syntax if you are familiar with it, for example:
ctab := crontab.New()
ctab.AddJob("*/5 * * * *", myFunc)
ctab.AddJob("0 0 * * *", myFunc2)
Package link: https://github.com/mileusna/crontab
This is another general implementation without need for a third party library.
Disclaimer: This implementation works with UTC. For managing timezones it has to be modified.
Run a func once a day at noon.
Period: time.Hour * 24
Offset: time.Hour * 12
Run a func twice a day at 03:40 (00:00 + 03:40) and 15:40 (12:00 + 03:40).
Period: time.Hour * 12
Offset: time.Hour * 3 + time.Minute * 40
Updated (2020-01-28):
Changes:
context.Context can be used for cancellation, makes it testable.
time.Ticker removes the need for calculating the time of the next execution.
package main
import (
"context"
"time"
)
// Schedule calls function `f` with a period `p` offsetted by `o`.
func Schedule(ctx context.Context, p time.Duration, o time.Duration, f func(time.Time)) {
// Position the first execution
first := time.Now().Truncate(p).Add(o)
if first.Before(time.Now()) {
first = first.Add(p)
}
firstC := time.After(first.Sub(time.Now()))
// Receiving from a nil channel blocks forever
t := &time.Ticker{C: nil}
for {
select {
case v := <-firstC:
// The ticker has to be started before f as it can take some time to finish
t = time.NewTicker(p)
f(v)
case v := <-t.C:
f(v)
case <-ctx.Done():
t.Stop()
return
}
}
}
Original:
package main
import (
"time"
)
// Repeat calls function `f` with a period `d` offsetted by `o`.
func Repeat(d time.Duration, o time.Duration, f func(time.Time)) {
next := time.Now().Truncate(d).Add(o)
if next.Before(time.Now()) {
next = next.Add(d)
}
t := time.NewTimer(next.Sub(time.Now()))
for {
v := <-t.C
next = next.Add(d)
t.Reset(next.Sub(time.Now()))
f(v)
}
}
I'm using https://github.com/ehsaniara/gointerlock. It's also supported in distributed systems and has a builtin distributer lock (Redis)
import (
"context"
"fmt"
"github.com/ehsaniara/gointerlock"
"log"
"time"
)
var job = gointerlock.GoInterval{
Interval: 2 * time.Second,
Arg: myJob,
}
err := job.Run(ctx)
if err != nil {
log.Fatalf("Error: %s", err)
}
func myJob() {
fmt.Println(time.Now(), " - called")
}