How can I calculate the number of days between two dates? In the code below I should get the number of hours, which means that I should only need to divide by 24. However, the result I get is something like -44929.000000. I'm only looking a day or two back so I would expect 24 or 48 hours.
package main
import (
"fmt"
"time"
)
func main() {
timeFormat := "2006-01-02"
t, _ := time.Parse(timeFormat, "2014-12-28")
fmt.Println(t)
// duration := time.Since(t)
duration := time.Now().Sub(t)
fmt.Printf("%f", duration.Hours())
}
Here's the executable Go code: http://play.golang.org/p/1MV6wnLVKh
Your program seems to work as intended. I'm getting 45.55 hours. Have you tried to run it locally?
Playground time is fixed, time.Now() will give you 2009-11-10 23:00:00 +0000 UTC always.
package main
import (
"fmt"
"time"
)
func main() {
date := time.Now()
fmt.Println(date)
format := "2006-01-02 15:04:05"
then,_ := time.Parse(format, "2007-09-18 11:58:06")
fmt.Println(then)
diff := date.Sub(then)
//func Since(t Time) Duration
//Since returns the time elapsed since t.
//It is shorthand for time.Now().Sub(t).
fmt.Println(diff.Hours())// number of Hours
fmt.Println(diff.Nanoseconds())// number of Nanoseconds
fmt.Println(diff.Minutes())// number of Minutes
fmt.Println(diff.Seconds())// number of Seconds
fmt.Println(int(diff.Hours()/24))// number of days
}
Here is the running code https://play.golang.org/p/Vbhh1cBKnh
the below code gives the list of all the days along with the number of days between the from date and to date:
you can click on the link for the code in
Go PlayGround:https://play.golang.org/p/MBThBpTqjdz
to := time.Now()
from := to.AddDate(0, -1, 0)
fmt.Println("toDate", to)
fmt.Println("fromDate", from)
days := to.Sub(from) / (24 * time.Hour)
fmt.Println("days", int(days))
noofdays := int(days)
for i := 0; i <= noofdays; i++ {
fmt.Println(from.AddDate(0, 0, i))
}
One caveat to be mindful of when using this technique of timeOne.Sub(timeTwo).Hours() / 24 is that daylights savings can cause a day to contain only 23 hours, throwing this calculation off slightly.
Happy programmer's day
package main
import (
"fmt"
"time"
)
func main() {
loc, _ := time.LoadLocation("UTC")
now := time.Now().In(loc)
firstDate := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, loc)
diff := now.Sub(firstDate)
fmt.Printf("The difference between %s and today %s es %d days\n", now.String(), firstDate.String(), int(diff.Hours()/24)+1)
// Just a joke
if ( int(diff.Hours()/24)+1 == 256 ) {
fmt.Printf("¡Happy programmer's day!")
} else {
fmt.Printf("On my computer it works...!?")
}
}
Related
I'm looking for a way to extract time from time.Time as time.Duration.
For instance,
"2022-11-25 10:07:40.1242844 +0900 JST"(time.Time)
to
"10h7m40s"(time.Duration)
func main() {
currentTime := time.Now()
d, err := time.ParseDuration(currentTime.Format("15h04m05s"))
if err != nil {
fmt.Println(err)
}
fmt.Print(d.String())
// 9h57m54s
}
This code works, but it once converts time to string and then converts to duration,
which I think it is roundabout, and I don't like it.
Is there a better way to write this code?
Another solution is to truncate the current time to the start of day, then use time.Since() to return a Duration:
import (
"fmt"
"time"
)
func main() {
now := time.Now()
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
fmt.Println(time.Since(today))
}
I'm making a cron job for the booking charge automatic. The admin set the automatic charge after 2 hour of booking completion then I Get all the booking completed before 2 hours from the current time and charge them automatic. But the problem arise in the end of the day is that current_date= 10/10/2018 current_time= 1:00AM and automatic_charge_hours= 2 (hours) means it will get all the bookings which are completed 2 hours before the current_time and current_date. In 24hour format it will get all the bookings of the 23 hours(11:00PM of date 09/10/2018) of the previous date . But in my condition it will turn it into zero below is my condition:-
package main
import (
"fmt"
"time"
"strings"
)
func main() {
timeZone, _ := time.LoadLocation("America/New_York")
currDate := time.Now().In(timeZone).Format("2006-01-02 00:00:00 -0000")
onlyDate := strings.Split(currDate, " ")
hours, _ := 1, 0
if hours-int(2) < 0 {
hours = 0
} else {
hours = hours - int(2)
}
fmt.Println(hours, onlyDate[0])
}
playground link https://play.golang.org/p/w7LIoTp9xN0
How will I change it. Any suggestions please.
if hours-int(2) < 0 {
hours = 0
} else {
hours = hours - int(2)
}
Explicitly sets hours to zero when hours are negative.
If you change hours = 0 to hours = 24 + (hours-int(2)) it returns 23.
See https://play.golang.org/p/FyXIn5gjIXk
Anyhow, Instead of manipulating hours by hand, you should use time functions.
Update: Use time functions:
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse("01.02.2006 03:04:00", "10.10.2018 01:00:00")
if err != nil {
panic(err)
}
then := t.Add(time.Duration( -2 ) * time.Hour)
fmt.Printf("%v\n", then)
}
https://play.golang.org/p/0r6q7Vvai2h
You only have to change the condition little bit for the hours like below:-
func main() {
timeZone, _ := time.LoadLocation("America/New_York")
currDate := time.Now().In(timeZone).Format("2006-01-02 00:00:00 -0000")
onlyDate := strings.Split(currDate, " ")
hours, _ := 1, 0
hours = hours-int(2)
fmt.Println(hours)
if hours <= -1 {
hours = 24 + hours
currDate = time.Now().In(timeZone).AddDate(0, 0, -1).Format("2006-01-02 00:00:00 -0000")
fmt.Println(currDate)
}
fmt.Println(hours, onlyDate[0])
}
AddDate() is the function in the time package you can see in the https://golang.org/pkg/time/
I'm trying to parse an Unix timestamp but I get out of range error. That doesn't really makes sense to me, because the layout is correct (as in the Go docs):
package main
import "fmt"
import "time"
func main() {
tm, err := time.Parse("1136239445", "1405544146")
if err != nil{
panic(err)
}
fmt.Println(tm)
}
Playground
The time.Parse function does not do Unix timestamps. Instead you can use strconv.ParseInt to parse the string to int64 and create the timestamp with time.Unix:
package main
import (
"fmt"
"time"
"strconv"
)
func main() {
i, err := strconv.ParseInt("1405544146", 10, 64)
if err != nil {
panic(err)
}
tm := time.Unix(i, 0)
fmt.Println(tm)
}
Output:
2014-07-16 20:55:46 +0000 UTC
Playground: http://play.golang.org/p/v_j6UIro7a
Edit:
Changed from strconv.Atoi to strconv.ParseInt to avoid int overflows on 32 bit systems.
You can directly use time.Unix function of time which converts the unix time stamp to UTC
package main
import (
"fmt"
"time"
)
func main() {
unixTimeUTC:=time.Unix(1405544146, 0) //gives unix time stamp in utc
unitTimeInRFC3339 :=unixTimeUTC.Format(time.RFC3339) // converts utc time to RFC3339 format
fmt.Println("unix time stamp in UTC :--->",unixTimeUTC)
fmt.Println("unix time stamp in unitTimeInRFC3339 format :->",unitTimeInRFC3339)
}
Output
unix time stamp in UTC :---> 2014-07-16 20:55:46 +0000 UTC
unix time stamp in unitTimeInRFC3339 format :----> 2014-07-16T20:55:46Z
Check in Go Playground: https://play.golang.org/p/5FtRdnkxAd
Sharing a few functions which I created for dates:
Please note that I wanted to get time for a particular location (not just UTC time). If you want UTC time, just remove loc variable and .In(loc) function call.
func GetTimeStamp() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
t := time.Now().In(loc)
return t.Format("20060102150405")
}
func GetTodaysDate() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
current_time := time.Now().In(loc)
return current_time.Format("2006-01-02")
}
func GetTodaysDateTime() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
current_time := time.Now().In(loc)
return current_time.Format("2006-01-02 15:04:05")
}
func GetTodaysDateTimeFormatted() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
current_time := time.Now().In(loc)
return current_time.Format("Jan 2, 2006 at 3:04 PM")
}
func GetTimeStampFromDate(dtformat string) string {
form := "Jan 2, 2006 at 3:04 PM"
t2, _ := time.Parse(form, dtformat)
return t2.Format("20060102150405")
}
I do a lot of logging where the timestamps are float64 and use this function to get the timestamps as string:
func dateFormat(layout string, d float64) string{
intTime := int64(d)
t := time.Unix(intTime, 0)
if layout == "" {
layout = "2006-01-02 15:04:05"
}
return t.Format(layout)
}
for millis unix timestamp precision, in go1.18
i, err := strconv.ParseInt("1652084489543", 10, 64)
if err != nil {
panic(err)
}
tm := time.UnixMilli(i)
fmt.Println(tm)
According to the go documentation, Unix returns a local time.
Unix returns the local Time corresponding to the given Unix time
This means the output would depend on the machine your code runs on, which, most often is what you need, but sometimes, you may want to have the value in UTC.
To do so, I adapted the snippet to make it return a time in UTC:
i, err := strconv.ParseInt("1405544146", 10, 64)
if err != nil {
panic(err)
}
tm := time.Unix(i, 0)
fmt.Println(tm.UTC())
This prints on my machine (in CEST)
2014-07-16 20:55:46 +0000 UTC
This is an old question but I noticed that a practical answer is missing.
For example, we are working with the MavLink protocol and we need to process a message with a structure defined here.
If we have this data structure:
Field Name
Type
Units
Description
time_boot_ms
uint64_t
ms
Timestamp (time since system boot).
press_abs
float
hPa
Absolute pressure
press_diff
float
hPa
Differential pressure 1
temperature
int16_t
cdegC
Absolute pressure temperature
temperature_press_diff **
int16_t
cdegC
Differential pressure temperature (0, if not available). Report values of 0 (or 1) as 1 cdegC.
So, we receive constant updates that we need to process using the time_boot_ms as reference to insert them on the database and synchronize them with other messages.
What can we do?
As we noticed, the time is in milliseconds and everyone, that has some experience with Go, knows that for some unknown reason it's just way too complex to convert a millisecond resolution Unix timestamp to time.Time. The built-in time.Unix() function only supports second and nanosecond precision.
How we can get millisecond precision?
Well, we might wait until they release the version 1.7 of Go or we either have to multiply the milliseconds to nanoseconds or split them into seconds and nanoseconds.
Lets implement the second idea, spit the into seconds and nanoseconds:
unixUTCtime := time.Unix(ms/int64(1000), (ms%int64(1000))*int64(1000000))
Now we can encapsulate it in a func and use it in our main like this:
package main
import (
"fmt"
"time"
)
const msInSecond int64 = 1e3
const nsInMillisecond int64 = 1e6
// UnixToMS Converts Unix Epoch from milliseconds to time.Time
func UnixToMS (ms int64) time.Time {
return time.Unix(ms/msInSecond, (ms%msInSecond)*nsInMillisecond)
}
func main() {
unixTimes := [...]int64{758991688, 758992188, 758992690, 758993186}
var unixUTCTimes []time.Time
for index, unixTime := range unixTimes {
unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))
if index > 0 {
timeDifference := unixUTCTimes[index].Sub(unixUTCTimes[index-1])
fmt.Println("Time difference in ms :--->", timeDifference)
}
}
}
The output will be:
Time difference in ms :---> 500ms
Time difference in ms :---> 502ms
Time difference in ms :---> 496ms
Check in Go Playground
I'm trying to pint the month, day, and year, separately to the console.
I need to be able to access each section of the date individually. I can get the whole thing using time.now() from the "time" package but I'm stuck after that.
Can anyone show me where I am going wrong please?
You're actually pretty close :) Then return value from time.Now() is a Time type, and looking at the package docs here will show you some of the methods you can call (for a quicker overview, go here and look under type Time). To get each of the attributes you mention above, you can do this:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t.Month())
fmt.Println(t.Day())
fmt.Println(t.Year())
}
If you are interested in printing the Month as an integer, you can use the Printf function:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Printf("%d\n", t.Month())
}
Day, Month and Year can be extracted from a time.Time type with the Date() method. It will return ints for both day and year, and a time.Month for the month. You can also extract the Hour, Minute and Second values with the Clock() method, which returns ints for all results.
For example:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
y, mon, d := t.Date()
h, m, s := t.Clock()
fmt.Println("Year: ", y)
fmt.Println("Month: ", mon)
fmt.Println("Day: ", d)
fmt.Println("Hour: ", h)
fmt.Println("Minute: ", m)
fmt.Println("Second: ", s)
}
Please remember that the Month variable (mon) is returned as a time.Month, and not as a string, or an int. You can still print it with fmt.Print() as it has a String() method.
Playground
You can just parse the string to get year, month, & day.
package main
import (
"fmt"
"strings"
)
func main() {
currTime := time.Now()
date := strings.Split(currTime.String(), " ")[0]
splits := strings.Split(date, "-")
year := splits[0]
month := splits[1]
day := splits[2]
fmt.Printf("%s-%s-%s\n", year, month, day)
}
Does anyone know how to check for a file access date and time? The function returns the modified date and time and I need something that compares the accessed date time to the current date and time.
You can use os.Stat to get a FileInfo struct which also contains the last access time (as well as the last modified and the last status change time).
info, err := os.Stat("example.txt")
if err != nil {
// TODO: handle errors (e.g. file not found)
}
// info.Atime_ns now contains the last access time
// (in nanoseconds since the unix epoch)
After that, you can use time.Nanoseconds to get the current time (also in nanoseconds since the unix epoch, January 1, 1970 00:00:00 UTC). To get the duration in nanoseconds, just subtract those two values:
duration := time.Nanoseconds() - info.Atime_ns
By casting os.FileInfo to *syscall.Stat_t:
package main
import ( "fmt"; "log"; "os"; "syscall"; "time" )
func main() {
for _, arg := range os.Args[1:] {
fileinfo, err := os.Stat(arg)
if err != nil {
log.Fatal(err)
}
atime := fileinfo.Sys().(*syscall.Stat_t).Atim
fmt.Println(time.Unix(atime.Sec, atime.Nsec))
}
}
Alternatively, after the Stat you can also do
statinfo.ModTime()
Also you can use Format() on it, should you need it eg for a webserver
see https://gist.github.com/alexisrobert/982674
For windows
syscall.Win32FileAttributeData
info, _ := os.Stat("test.txt")
fileTime := info.Sys().(*syscall.Win32FileAttributeData).LastAccessTime
aTime := time.Unix(0, fileTime.Nanoseconds())
Example
package main
import (
"fmt"
"log"
"os"
"syscall"
"time"
)
func main() {
info, _ := os.Stat("./test.txt")
fileTime := info.Sys().(*syscall.Win32FileAttributeData).LastAccessTime
// _ = info.Sys().(*syscall.Win32FileAttributeData).CreationTime
// _ = info.Sys().(*syscall.Win32FileAttributeData).LastWriteTime
fileAccessTime := time.Unix(0, fileTime.Nanoseconds())
// Compare
// t2, _ := time.Parse("2006/01/02 15:04:05 -07:00:00", "2023/02/08 13:18:00 +08:00:00")
now := time.Now()
log.Println(fileAccessTime)
log.Println(now.Add(-20 * time.Minute))
if fileAccessTime.After(now.Add(-20 * time.Minute)) {
fmt.Println("You accessed this file 20 minutes ago.")
}
}
Linux
see this answer