"month out of range" when parsing date without separators - date

Any ideas how to get golang to properly parse a date string such as 31916
I keep getting a month out of range error.
date, err := time.Parse("1206", "31916")
fmt.Println(date, err)
Of course I want to treat the month as 3 and not 31 like it's doing, but I'm not sure how to force it to stop at 3 for the month outside of adding separators to the format.

For example,
package main
import (
"fmt"
"time"
)
func parseDate(date string) (time.Time, error) {
if len(date) == 5 {
date = "0" + date
}
return time.Parse("010206", date)
}
func main() {
date, err := parseDate("31916")
fmt.Println(date, err)
date, err = parseDate("031916")
fmt.Println(date, err)
date, err = parseDate("121916")
fmt.Println(date, err)
}
Output:
2016-03-19 00:00:00 +0000 UTC <nil>
2016-03-19 00:00:00 +0000 UTC <nil>
2016-12-19 00:00:00 +0000 UTC <nil>

You can't. The layout you pass is not deterministic - there is no way for Go to know when the month ends and the day starts in your string - besides when one option fails and the other one does not (think of "11106" - is that 1\11\06 or 11\1\06?). Your best bet is to write a wrapper which makes the choice deterministic:
import (
"time"
"strconv"
)
func parseWeirdLayout(dateString string) (time.Time, error) {
parsedString := ""
if len(dateString) == 5 {
month, err := strconv.Atoi(dateString[0:2])
if err != nil {
return time.Now(), err
}
if month < 1 || month > 12 {
parsedString = "0" + dateString
} else {
parsedString = dateString[:2] + "0" + dateString[2:]
}
} else if len(dateString) == 4 {
parsedString = "0" + dateString[:1] + "0" + dateString[1:]
}
return time.Parse("010206", parsedString)
}
Test here: https://play.golang.org/p/u1QFPzehMj
Or simply use a different, deterministic layout, e.g. "010206".

Related

subtract time now from gorm create at in golang

I am trying to do find the time difference between time now from the created at column in the database
I return a row in the database, i have the created_at column with the following time format
{"id":1,"email":"fUPvyBA#FApYije.ru","timezone":"pacific time","created_at":"2022-01-23T02:45:01.241589Z","updated_at":"2022-01-23T02:46:01.241591Z"}
so created_at = 2022-01-23T02:45:01.241589Z
and
time.Now() = 2022-01-24 03:24:56.215573343 +0000 UTC m=+1325.103447033
I tested with the following
import (
"fmt"
"time"
)
func TestTime() {
timestart := "2022-01-23T02:45:01.241589Z"
timeend := time.Now()
timediff := timeend.Sub(timestart)
fmt.Println("time diff is: ", timediff.Seconds())
}
TestTime()
but i get the following errors
cannot use <string> as <time.Time> in argument to timeend.Sub
How do i subtract to get the difference between the time i stored in created_at column from the current time time.Now()?
The error means that you trying to use an string on a time.Time parameter
Try this:
import (
"fmt"
"time"
)
func TestTime() {
layout := time.RFC3339 // "2006-01-02T15:04:05Z07:00"
timestart, err := time.Parse(layout, "2022-01-23T02:45:01.241589Z")
if err != nil {
panic(err)
}
timeend := time.Now()
timediff := timeend.Sub(timestart)
fmt.Println("time diff is:", ltimediff.Seconds())
}
TestTime()

How to get time difference in hours in a custom date format in Go

I need help with comparison this type of format date help and I want to print a comparison delay by hours
createdAt := msg.Header.Get("Date") // string: Sun, 03 May 2020 16:37:40 +0000 (UTC)
t, err := time.Parse("i don't have this", createdAt)
if err != nil {
fmt.Println(err)
}
// some code here idk - comparison createdAt with date/time now
fmt.Printf("Lifespan is %+v", diff)
output:
Lifespan is 3h
The net/http package has a helper function exactly for parsing times from headers, trying all HTTP-compliant formats: http.ParseTime(). So you should definitely try that.
t, err := http.ParseTime(createdAt)
if err != nil {
// Handle error
}
if t.Before(time.Now()) {
fmt.Println("It's in the past")
} else {
fmt.Println("It's in the future")
}
There's a catch though: your time doesn't seem to be in a valid HTTP/1.1 time format, but rather described by the following layout:
"Mon, 02 Jan 2006 15:04:05 -0700 (MST)"
So you may parse it like:
t, err := time.Parse("Mon, 02 Jan 2006 15:04:05 -0700 (MST)", createdAt)
if err != nil {
panic(err) // Handle error
}
delta := time.Since(t)
fmt.Println("Time since createdAt:", delta)
if delta < 0 {
fmt.Println("It's in the past")
} else {
fmt.Println("It's in the future")
}
It outputs (try it on the Go Playground):
Time since createdAt: -91841h37m40s
It's in the past
You can use a format string to parse string to get time.Time type data
createdAt := "Sun, 03 May 2020 16:37:40 +0000 (UTC)"
format := "Mon, 02 Jan 2006 15:04:05 +0000 (MST)"
t, err := time.Parse(format, createdAt)
To get the duration between two date use .Sub() function which return duration in time.Duration type. And to get the duration in hour use .Hours() function of time.Duration.
now := time.Now()
diff := now.Sub(t)
fmt.Printf("Lifespan is %f", diff.Hours())
Full code in go playground here

how to check if due-date in rest api is greater than tomorrow [duplicate]

This question already has answers here:
How to do date/time comparison
(9 answers)
Closed 2 years ago.
I've written a todo handler API and want to add a condition to check if inputted DueDate by user is less than tomorrow date,how should I write it instead of ???? in following code?
type Todo struct {
gorm.Model
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
DueDate time.Time `json:"duedate,omitempty"`
UserId uint `json:"user_id"` //The user that this todo belongs to
}
func ValidateTodo(todo *Todo) (map[string]interface{}, bool) {
if todo.Title == "" {
return u.Message(false, "Todo title should be on the payload"), false
}
if len(todo.Title)>30 {
return u.Message(false, "Todo title should be less than 30 characters"), false
}
if todo.Description == "" {
return u.Message(false, "Todo description should be on the payload"), false
}
if todo.DueDate<time.Now(){
?????
}
return u.Message(true, "success"), true
}
You an do this with a combination of time.AddDate() and time.Before()
dueDate := time.Now()
tomorrow := time.Now().AddDate(0, 0, 1)
if tomorrow.Before(dueDate) {
fmt.Println("Tomorrow is before your due date")
}
Edit: Volker's comment raises a good point actually. time.After() would probably make more logical sense to use for readability. So you could do the following;
dueDate := time.Now()
tomorrow := time.Now().AddDate(0, 0, 1)
if dueDate.After(tomorrow) {
fmt.Println("Due date is after tomorrow")
}
Edit2: Update to zero out time based on the desire to have tomorrow's time at 00:00:00
tomorrow := time.Now().AddDate(0, 0, 1)
tomorrowZeroTime, err := time.Parse("Mon Jan 2 2006", tomorrow.Format("Mon Jan 2 2006"))
if err != nil {
// Handle Error
}
dueDate := time.Now()
if dueDate.After(tomorrowZeroTime) {
fmt.Println("Due date is after tomorrow")
}

Difference between the past date time and current time in minutes in golang

I have current time and past time, Im trying to findout difference in minutes.
Here is my code im trying, although im new to go.
package main
import (
"fmt"
"time"
)
func main() {
//fetching current time
currentTime := time.Now().Format("2006-01-02 15:04:05")
//past time comes in as string
pasttimestr := "2018-10-10 23:00"
layout := "2006-01-02 15:04:05"
//converting string to date
pasttime, err := time.Parse(layout, pasttimestr)
if err != nil {
fmt.Println(err)
}
//differnce between pastdate and current date
diff := currentTime.Sub(pasttime)
fmt.Println("difference time in min : ", diff)
}
Error:
# command-line-arguments
.\dates.go:21:21: currentTime.Sub undefined (type string has no field or method Sub)
Thanks in advance :)
You should probably remove the format function call from current time to get the actual time struct rather than a string representation and and fix the layout for past time
package main
import (
"fmt"
"time"
)
func main() {
//fetching current time
currentTime := time.Now()
loc := currentTime.Location()
//past time comes in as string
pasttimestr := "2018-10-10 23:00"
layout := "2006-01-02 15:04"
//converting string to date
pasttime, err := time.ParseInLocation(layout, pasttimestr, loc)
if err != nil {
fmt.Println(err)
}
fmt.Println("Past Time: ", pasttime)
fmt.Println("Current Time: ", currentTime)
//differnce between pastdate and current date
diff := currentTime.Sub(pasttime)
fmt.Printf("time difference is %v or %v in minutes\n", diff, diff.Minutes())
}
Gives me
Past Time: 2018-10-10 23:00:00 -0400 EDT
Current Time: 2018-10-10 14:31:34.865259 -0400 EDT m=+0.000351797
time difference is -8h28m25.134741s or -508.41891235 in minutes
Drop the .Format() function call on time.Now() like below. Also I've updated the layout string to match the format for pasttimestr.
func main() {
//fetching current time
currentTime := time.Now()
//past time comes in as string
pasttimestr := "2018-10-10 23:00"
layout := "2006-01-02 15:04"
//converting string to date
pasttime, err := time.Parse(layout, pasttimestr)
if err != nil {
fmt.Println(err)
}
//differnce between pastdate and current date
diff := currentTime.Sub(pasttime)
fmt.Println("difference time is : ", diff)
}
Output
difference time is : -4h36m32.001213s

How to compare 2 dates with each other. Dates are converted to String

I want to sort my tableview on date. I know I can do that by using:
array.sort {
$0.date! < $1.date!
}
Problem is that the date is converted to a String. The date is saved in core data and changing the attribute date to NSDate is causing problems. SO how can I compare the dates without changing my Core Data?
Update for swift 3 :
if you want to compare date objects, used below lines of code:
extension Date {
func isGreater(than date: Date) -> Bool {
return self >= date
}
func isSmaller(than date: Date) -> Bool {
return self < date
}
func isEqual(to date: Date) -> Bool {
return self == date
}
}
// how to call it?
let isGreater = end_date.isGreater(than: start_date)
// where end_date and start_date is your date objects.
You should be able to sort by strings, what is your string date format?
Here is an example of sorting dates with strings:
let date1 = Date()
let date2 = Date().addingTimeInterval(TimeInterval.abs(60.0))
let date3 = Date().addingTimeInterval(TimeInterval.abs(60 * 60 * 24))
var arrayOfDates = [date1.description, date2.description, date3.description]
let sorted = arrayOfDates.sorted { $0.0 > $0.1 }
print(sorted.first!)
print(sorted[1])
print(sorted[2])
output:
2016-10-31 18:33:32 +0000
2016-10-30 18:34:32 +0000
2016-10-30 18:33:32 +0000
switching sorted to:
let sorted = arrayOfDates.sorted { $0.0 < $0.1 }
gives the following outside:
2016-10-30 18:35:58 +0000
2016-10-30 18:36:58 +0000
2016-10-31 18:35:58 +0000