how to convert duration to days in Go - go

In Go, how can I convert duration to number of days?
for eg 1W => 7days, 1Y => 365days etc.

The short answer, for many common purposes, is just to divide the number of hours by 24, to get a generally useful approximation of the number of days.
d, _ := time.ParseDuration("48h")
days := d.Hours()/24 // 2 days
However, this isn't always "correct", depending on your situation. Consider:
How many days between November 1, 2018 midnight and November 8, 2018 midnight? The answer actually depends on at least two things: Your definition of day, and where you're located. If you calculate the duration between the two dates, and divide as described above, your answer will be 7.04167 days, if you're located in the US, due to the daylight savings change.
If your time period happens at the right time in the spring, your answer might be 6.95833 days, due to the DST change in the other direction.
If you account for multiple timezones, leap seconds, or other aberation from "normal", you can end up with even more confusing results.
For some purposes, 7.04167 days would be the right answer. For other purposes, 7 would be the right answer.
So the first task, when trying to calculate "days" is always to determine what definition matters to you. Then second, figure out how to calculate a meaningful number that satisfies that need.

you can try this pkg: https://github.com/hako/durafmt
package main
import (
"fmt"
"github.com/hako/durafmt"
)
func main() {
duration, err := durafmt.ParseString("354h22m3.24s")
if err != nil {
fmt.Println(err)
}
fmt.Println(duration) // 2 weeks 18 hours 22 minutes 3 seconds
// duration.String() // String representation. "2 weeks 18 hours 22 minutes 3 seconds"
}

Related

Is there an easy way to change the hour of an existing time?

So far the best that I have is this, which is long and it's easy to make a mistake:
cst, _ := time.LoadLocation("Asia/Shanghai")
orig := time.Now().In(cst)
new := time.Date(orig.Year(), orig.Month(), orig.Day(), 13, orig.Minute(), orig.Second(), orig.Nanosecond(), cst)
fmt.Printf("%v", new)
https://play.golang.org/p/dv_7rltueY6
It may seem easier to do arithmetic with durations.
// NO!
// const newHour = 13
// d := orig.Add(time.Duration(newHour - orig.Hour()) * time.Hour)
However, this won't work during daylight savings. Your original code is about as correct as it can be... the time.Date() function will account for daylight savings, although there are certain edge cases with no good answer (what happens when you set the time to 1:30AM when the clocks go forward in North American eastern time?)

How to get time in seconds with add time zone in go

I am using time.Time in go. to get time in seconds (the number of seconds elapsed since 1970's January 1) I am using
now := Time.now()
loc, err := time.LoadLocation(country.Timezone) // time zone in Asia/Dhaka
now = now.In(loc)
then,
seconds := now.Unix()
but the seconds giving seconds without adding the time zone seconds. it actually giving the seconds in UTC. My question is, how can I get seconds with added 6 hours ( asia/dhaka time zone is UTC+6)?
If you want current clock time's second part only use below code:
loc := time.FixedZone("some_common_name", 6*60*60)
ts := time.Now().In(loc).Second()
fmt.Println(ts)
If you want seconds from start of current year(like 01.01.1970)
loc := time.FixedZone("some_common_name", 6*60*60)
tp := time.Date(1970, 1, 1, 0, 0, 0, 0, loc)
ts := time.Now().Sub(tp).Seconds()
fmt.Printf("%v", ts)
In case, you want different time zone information, change offset value of time.FixedZone() functions. As, if you want GMT +5, then use 5*60*60 as offset value
I've read a number of posts and most of them are rightfully biased that Unix() time should be exactly that; meaning UTC. However, In my particular case others, like the TCL team, are a little loose. Both input and output allow the user to override the TZ. Furthermore the default TZ has it's own rules.
In my case I was not even using times... only dates. However, the closer to the date boundary the more likely it change days and thus bang up the date expressions etc.
In TCL there is UTC seconds from 1/1/1970 but there is also TZ adjusted seconds from 1/1/1970. (right or wrong I need some compatibility)
// parse the time string (the value does not have the TZ)
t, _ := time.Parse(format, value)
// set the location.
t = t.In(location)
// get the offset seconds from TZ
_, offset := t.Zone()
// adjust the Unix() seconds by the offset.
retval = fmt.Sprintf("%d", t.Unix()-int64(offset))
I'm in EST5EDT and it works here when location is EST5EDT and Local. I did not try anything on the other side of the UTC.
UPDATE: Well... Someone once said show me a programmer who knows dates and times and I'll show you someone who doesn't. The code above worked just fine as Local and UTC were on the same calendar day. But as soon as UTC moved into the next calendar day the Seconds were exactly 24hrs apart. I can squeeze the last second out of this so that TCL and my app work similarly but I'm better off doing this in the app code rather than in the libs.

What is the value of the ISO 8601 duration `P1M` (in seconds)?

Suppose I have an ISO 8601 duration, expressed as "P1M". Phrased colloquially, this means "one month." Is there a standard rule for converting this into a number of seconds, assuming the start date is not known?
For 30-day months, it might be 2,592,000.
For 31-day months, it might be 2,678,400.
In February, it might be 2,419,200 or it might be 2,505,600.
My gut says there's no way to resolve "one month" to an exact number of seconds without knowing context, and where those seconds are laid out on the calendar. But are there standard rules/conventions to calculate these durations in an abstract way?
From ISO 8601 documentation that I found (page 6 - http://xml.coverpages.org/ISO-FDIS-8601.pdf), it seems you are correct in that the number of seconds in a month cannot definitively be determined. However it does note that "In certain applications a month is regarded as a unit of time of 30 days", so depending on your application this may be a valid approach.
The distinction between "Calendar Time" (Years, Months, etc) and "Absolute Time" (Hours, Minutes, Seconds, etc) is sometimes an important one. As an example, some people might complain about having 13 mortgage payments some years if they paid every 30 days as opposed to every month.
You are right, an ISO 8601 duration is dependent of the context.
A duration is a period/an interval of time between two dates.
Example :
2020-01-01/2020-02-01 = P1M = P31D
2020-02-01/2020-03-01 = P1M = P29D
2019-02-01/2019-03-01 = P1M = P28D
If you want a fixed duration indepedent of the context, use the day notation P30D, P60D, P90D... instead.
The same applies for years :
2019-01-01/2020-01-01 = P1Y = P12M = P365D
2020-01-01/2021-01-01 = P1Y = P12M = P366D
If you can't have context information about a duration, for example P1M retrieved from database or given by user input, use by default today's context.
//What is a duration of one month in seconds ?
P1M = ? (no context)
//Use default context
Today = 2020-03-31
2020-03-31/P1M = 2020-03-31/2020-04-30
=> P1M = P30D
//A month contains 2 592 000 seconds

Simple Add to time and compare GO

Hi I can't seem to get my head around the correct way to do time arithmetic in Go.
I have a time "object" later initialized to Now() and stored.
insertTime time.Time
Later, I need to see if the item is older than 15 minutes.
How do i do this?
Do I need to create a Duration of 15 Minutes add it to the current time and compare? If so, how do I do that?
func (Time) After will be helpful, I believe. Schema:
when := time.Now()
...
if time.Now().After(when.Add(15*time.Minute)) {
// Conditionally process something if at least 15 minutes elapsed
}
Instead of a variable, when could be a field of some struct, for example.
Alternative approach:
deadline := time.Now().Add(15*time.Minute)
...
if time.Now().After(deadline) {
// Conditionally process something if at least 15 minutes elapsed
}
I prefer the later version personally.

Are the Date, Time, and DateTime classes necessary?

What is the purpose of having Date and Time classes when there is a DateTime class that can handle both?
To summarize what the common ruby time classes are:
Time
This is the basic workhorse core ruby time class.
Has date and time attributes (year, month, day, hour, min, sec, subsec)
Based on floating-point second intervals from unix epoch (1970-01-01)
Can handle negative times before unix epoch
Can handle time arithmetic in units of seconds
Natively works in either UTC or "local" (system time zone)
There are really 3 kinds of Time object when it comes to dealing with time zones, let's look at a summer time to show DST:
utc = Time.utc(2012,6,1) # => 2012-12-21 00:00:00 UTC
utc.zone # => "UTC"
utc.dst? # => false
utc.utc? # => true
utc.utc_offset # => 0
local = Time.local(2012,6,1) # => 2012-06-01 00:00:00 -0700
local.zone # => "PDT"
local.dst? # => true
local.utc? # => false
local.utc_offset # => -25200
nonlocal = Time.new(2012,6,1,0,0,0, "-07:00") # => 2012-06-01 00:00:00 -0700
nonlocal.zone # => nil
nonlocal.dst? # => false
nonlocal.utc? # => false
nonlocal.utc_offset # => -25200
The last 2 look similar, but beware: you should not do arithmetic with a non-local Time. This is simply a time with a UTC offset and no zone, so it doesn't know the rules of DST. Adding time over the DST boundary will not change the offset and the resulting time-of-day will be wrong.
ActiveSupport::TimeWithZone
This one is worth mentioning here since it's what you use in Rails. Same as Time, plus:
Can handle any time zone
Respects DST
Can convert times between zones
I generally always reach for this when ActiveSupport is available as it takes care of all the time zone pitfalls.
Date
Has date attributes only (year, month, day)
Based on integer whole-day intervals from an arbitrary "day zero" (-4712-01-01)
Can handle date arithmetic in units of whole days
Can convert between dates in the ancient Julian calendar to modern Gregorian
Date is more useful than Time whenever you deal in whole days: no time zones to worry about! (I'm surprised this doesn't deal with the modern Persian calendar since it knows about the obsolete Julian calendar from centuries ago.)
DateTime
Has date and time attributes (year, month, day, hour, min, sec)
Based on fractions of whole-day intervals from an arbitrary "day zero" (-4712-01-01)
Can handle date arithmetic in units of whole days or fractions
Personally, I never have reason to use this: it's slow, it handles time without considering time zones, and it has an inconsistent interface. I find it leads to confusion whenever you assume you have a Time-like object, but it actually behaves like a Date instead:
Time.new(2012, 12, 31, 0, 0, 0) + 1 == Time.new(2012, 12, 31, 0, 0, 1)
DateTime.new(2012, 12, 31, 0, 0, 0) + 1 == DateTime.new(2013, 1, 1, 0, 0, 0)
Further, it has a meaningless "zone" attribute (note how non-local Time objects warn you that zone == nil), and you can't know anything else about it before turning it into a Time first:
dt = DateTime.new(2012,12,6, 1, 0, 0, "-07:00")
dt.zone # => "-07:00"
dt.utc? # => NoMethodError: undefined method `utc?'
dt.dst? # => NoMethodError: undefined method `dst?'
dt.utc_offset # => NoMethodError: undefined method `utc_offset'
Dealing with microseconds to check for rounding is also a little strange. You would think that because it doesn't have a usec attribute that it only deals in whole numbers, but you'd be wrong:
DateTime.now.usec # => NoMethodError: undefined method `usec'
DateTime.now.to_time.usec => 629399
In short, unless you're dealing with astronomical events in the ancient past and need to convert the Julian date (with time of day) to a modern calendar, please don't use DateTime. If anyone has an actual use case for this class, I'd love to read your comments.
I know there is an accepted answer but I have something to add. The Date class is a heavyweight, academic strength class. It can handle all sorts of RFC's, parse the strangest things and converts julian dates from thousand years ago to gregorian with the reform date of choice. The Time class is lightweight and it does not know of any of this stuff. It's cheaper and that shows up in a benchmark:
require 'benchmark'
require 'date'
Benchmark.bm(10) do |x|
x.report('date'){100000.times{Date.today} }
x.report('datetime'){100000.times{DateTime.now} }
x.report('time'){100000.times{Time.now} }
end
Result:
user system total real
date 1.250000 0.270000 1.520000 ( 1.799531)
datetime 6.660000 0.360000 7.020000 ( 7.690016)
time 0.140000 0.030000 0.170000 ( 0.200738)
(Ruby 1.9.2)
DateTime is a subclass of Date, so whatever you can do with Date can be done with DateTime. But as tadman and steenslag point out, DateTime is slower. See steenslag's answer for how much slower it is.
With respect to DateTime vs, Time, I found something here:
Time is a wrapper around Unix-Epoch.
Date (and DateTime) use rational and a "day zero" for storage. So Time is faster but the upper and lower bounds are tied to epoch time (which for 32bit epoch times is something around 1970-2040...while Date (and DateTime) have an almost infinite range but are terribly slow.
In short, DateTime is an all around superstar, and should be preferred in general, but if you want to optimize to the last bit, using Time can improve performance.
Another way of thinking of this is that Date and DateTime model time in terms of clocks and calendars, which is useful for describing times to users, and scheduling events. Having a Date without a time is nice for when you don't care about the time, and you don't want to think about time zones.
Time models time as a continuum, and is a wrapper around the Unix timestamp, which is just an integer. This is useful for all manner of internal applications where the computer doesn't care much whether a calendar boundary has been crossed, but just how many seconds (or milliseconds) have elapsed.
Yes. Date handles only the date for something, I.E., March 31, 1989. But it does not handle Time, for example, 12:30 PM.
DateTime, can handle both, March 31, 1989 12:30 PM EST.
Sometimes you don't need all parts of the DateTime. For example, you wanted to know when the use signed up for you website, Date would be useful here, because the time is eventually irrelevant.
In some cases you might want just the time. For example, if it's lunch time, you may want to tell the user your office is closed. At this point, the Data is irrelevant.
However, in most cases DateTime is used, because it can be used as either date, time, or both.

Resources