I'm trying to format the current time using this format yyyyMMddHHmmss.
t := time.Now()
fmt.Println(t.Format("yyyyMMddHHmmss"))
That is outputting:
yyyyMMddHHmmss
Any suggestions?
Use
fmt.Println(t.Format("20060102150405"))
as Go uses following constants to format date,refer here
const (
stdLongMonth = "January"
stdMonth = "Jan"
stdNumMonth = "1"
stdZeroMonth = "01"
stdLongWeekDay = "Monday"
stdWeekDay = "Mon"
stdDay = "2"
stdUnderDay = "_2"
stdZeroDay = "02"
stdHour = "15"
stdHour12 = "3"
stdZeroHour12 = "03"
stdMinute = "4"
stdZeroMinute = "04"
stdSecond = "5"
stdZeroSecond = "05"
stdLongYear = "2006"
stdYear = "06"
stdPM = "PM"
stdpm = "pm"
stdTZ = "MST"
stdISO8601TZ = "Z0700" // prints Z for UTC
stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
stdNumTZ = "-0700" // always numeric
stdNumShortTZ = "-07" // always numeric
stdNumColonTZ = "-07:00" // always numeric
stdFracSecond0 = ".0", ".00" // trailing zeros included
stdFracSecond9 = ".9", ".99" // trailing zeros omitted
)
This question comes in top of Google search when you find "golang current time format" so, for all the people that want to use another format, remember that you can always call to:
t := time.Now()
t.Year()
t.Month()
t.Day()
t.Hour()
t.Minute()
t.Second()
For example, to get current date time as "YYYY-MM-DDTHH:MM:SS" (for example 2019-01-22T12:40:55) you can use these methods with fmt.Sprintf:
t := time.Now()
formatted := fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d",
t.Year(), t.Month(), t.Day(),
t.Hour(), t.Minute(), t.Second())
As always, remember that docs are the best source of learning: https://golang.org/pkg/time/
Option 1: Go standard library
t.Format("20060102150405")
Unit
Golang Layout
Examples
Note
Year
06
21, 81, 01
Year
2006
2021, 1981, 0001
Month
January
January, February, December
Month
Jan
Jan, Feb, Dec
Month
1
1, 2, 12
Month
01
01, 02, 12
Day
Monday
Monday, Wednesday, Sunday
Day
Mon
Mon, Wed, Sun
Day
2
1, 2, 11, 31
Day
02
01, 02, 11, 31
zero padded day of the month
Day
_2
⎵1, ⎵2, 11, 31
space padded day of the month
Day
002
001, 002, 011, 031, 145, 365, 366
zero padded day of the year
Day
__2
⎵⎵1, ⎵⎵2, ⎵11, ⎵31, 365, 366
space padded day of the year
Part of day
PM
AM, PM
Part of day
pm
am, pm
Hour 24h
15
00, 01, 12, 23
Hour 12h
3
1, 2, 12
Hour 12h
03
01, 02, 12
Minute
4
0, 4 ,10, 35
Minute
04
00, 04 ,10, 35
Second
5
0, 5, 25
Second
05
00, 05, 25
10-1 to 10-9 s
.0 .000000000
.1, .199000000
Trailing zeros included
10-1 to 10-9 s
.9 .999999999
.1, .199
Trailing zeros omitted
Time zone
MST
UTC, MST, CET
Time zone
Z07
Z, +08, -05
Z is for UTC
Time zone
Z0700
Z, +0800, -0500
Z is for UTC
Time zone
Z070000
Z, +080000, -050000
Z is for UTC
Time zone
Z07:00
Z, +08:00, -05:00
Z is for UTC
Time zone
Z07:00:00
Z, +08:00:00, -05:00:00
Z is for UTC
Time zone
-07
+00, +08, -05
Time zone
-0700
+0000, +0800, -0500
Time zone
-070000
+000000, +080000, -050000
Time zone
-07:00
+00:00, +08:00, -05:00
Time zone
-07:00:00
+00:00:00, +08:00:00, -05:00:00
In Golang 1.17+ for fraction of seconds (.999 or .000) you can use , instead of . (,999 or ,000) but output is always with .!!! See https://github.com/golang/go/issues/48037
Option 2: strftime Go implementation
import strftime "github.com/itchyny/timefmt-go"
strftime.Format(t, "%Y%m%d%H%M%S")
See for more info
https://github.com/itchyny/timefmt-go
https://linux.die.net/man/3/strftime
import("time")
layout := "2006-01-02T15:04:05.000Z"
str := "2014-11-12T11:45:26.371Z"
t, err := time.Parse(layout, str)
if err != nil {
fmt.Println(err)
}
fmt.Println(t)
gives:
>> 2014-11-12 11:45:26.371 +0000 UTC
Time package in Golang has some methods that might be worth looking.
func (Time) Format
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time,
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the desired output. The same display rules will then be applied to the time value. Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and convenient representations of the reference time. For more information about the formats and the definition of the reference time, see the documentation for ANSIC and the other constants defined by this package.
Source (http://golang.org/pkg/time/#Time.Format)
I also found an example of defining the layout (http://golang.org/src/pkg/time/example_test.go)
func ExampleTime_Format() {
// layout shows by example how the reference time should be represented.
const layout = "Jan 2, 2006 at 3:04pm (MST)"
t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
fmt.Println(t.Format(layout))
fmt.Println(t.UTC().Format(layout))
// Output:
// Nov 10, 2009 at 3:00pm (PST)
// Nov 10, 2009 at 11:00pm (UTC)
}
Go standard library: time
now := time.Now()
fmt.Println(now) // 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
fmt.Println(now.Format("20060102150405"))
fmt.Println(now.Format("2006/01/02/15/04/05"))
fmt.Println(now.Format("2006-01-02 15:04:05"))
fmt.Println(now.Format("2006-01-02 15:04"))
fmt.Println(now.Format("2006/01/02 15:04:05"))
fmt.Println(now.Format("2006/01/02 15:04:05 (-0700)"))
fmt.Println(now.Format("2006年01月02日 15:04"))
fmt.Println(now.Format(time.Layout)) // 01/02 03:04:05PM '06 -0700
fmt.Println(now.Format(time.ANSIC)) // Mon Jan _2 15:04:05 2006
fmt.Println(now.Format(time.UnixDate)) // Mon Jan _2 15:04:05 MST 2006
fmt.Println(now.Format(time.RubyDate)) // Mon Jan 02 15:04:05 -0700 2006
fmt.Println(now.Format(time.RFC822)) // 02 Jan 06 15:04 MST
fmt.Println(now.Format(time.RFC850)) // Monday, 02-Jan-06 15:04:05 MST
fmt.Println(now.Format(time.Kitchen)) // 3:04PM
fmt.Println(now.Format(time.Stamp)) // Jan _2 15:04:05
Go playground
Related
I got a bit problem when calculating the time difference from PM to AM or vice versa. For instance:
ref, _ := time.Parse("03:04pm", "11:59pm")
t, _ := time.Parse("03:04am", "12:00am")
fmt.Println(t.Sub(ref).Minutes()) // Got -719, my expectation is 1 (minutes)
Actually that's true, but I want to get the smallest difference.
The reason you got -719 is that you do not provide date information and in second time.Parse you have typo in template. Template has to contain pm
time.Parse("03:04pm", "11:59pm") // 0000-01-01 23:59:00 +0000 UTC
time.Parse("03:04am", "12:00am") // 0000-01-01 12:00:00 +0000 UTC
You need to provide day information and pm in template
time.Parse("02 03:04pm", "01 11:59pm") // 0000-01-01 23:59:00 +0000 UTC
time.Parse("02 03:04pm", "02 12:00am") // 0000-01-02 00:00:00 +0000 UTC
see https://stackoverflow.com/a/69338568/12301864
I cant get the next 15th day but not the working day.
DateTime.now.next_day(+15).strftime('%d %^B %Y')
how can i get the next 15th weekday?
You're just adding 15 days to the current date. What you want is to adjust the date:
date = DateTime.now
if (date.mday > 15)
date = date.next_month
end
date = date.next_day(15 - date.mday)
Where that adjusts to be the 15th of the next month if it's already past the 15th of the current month.
Now this can be extended to be an Enumerator:
def each_mday(mday, from: nil)
from ||= DateTime.now
Enumerator.new do |y|
loop do
if (from.mday > mday)
from = from.next_month
end
from = from.next_day(mday - from.mday)
y << from
from += 1
end
end
end
Which makes it possible to find the first day matching particular criteria, like being a weekday:
each_mday(15, from: Date.parse('2019-06-14')).find { |d| (1..5).include?(d.wday) }
Where that returns July 15th, as June 15th is a weekend.
The from argument is optional but useful for testing cases like this to ensure it's working correctly.
15.times.reduce(Date.civil 2019, 03, 24) do |acc, _|
begin
acc += 1
end while [0, 6].include? acc.wday
acc
end
#⇒ #<Date: 2019-04-12 ((2458586j,0s,0n),+0s,2299161j)>
So you want to add 15 business days from the current date. You can go with iGian or Aleksei vanilla ruby answers or use business_time gem:
15.business_days.from_now
If I understood correctly, you want to get next Monday if you hit Saturday or Sunday. Since wday gives you 0 for Sun and 6 for Sat, you can use it to as a conditional to add days towards Monday.
def date_add_next_week_day(days)
date = (Date.today + days)
date += 1 if date.wday == 6
date += 1 if date.wday == 0
date
end
date_add_next_week_day(15).strftime('%d %^B %Y')
If I get the point you need to find the 15th day after a specified date, skipping weekends.
One possible option is to define the skipping_weekend hash like this, considering Date.html#wday:
skip_weekend = { 6 => 2, 0 => 1}
skip_weekend.default = 0
Then:
next15 = DateTime.now.next_day(15)
next15_working = next15.next_day(skip_weekend[next15.wday]).strftime('%d %B %Y')
Now if next15 falls on a working day, next15_working is the same day (hash defaults to 0), otherwise it skips 2 days if Saturday (6th week day, hash maps to 2) or 1 day if Sunday (0th week day, hash maps to 1)
I assume that, given a starting date, ds (a Date object), and a positive integer n, the problem is determine a later date, dt, such that between ds+1 and dt, inclusive, there n weekdays.
require 'date'
def given_date_plus_week_days(dt, week_days)
wday = dt.wday
weeks, days = (week_days + {0=>4, 6=>4}.fetch(wday, wday-1)).divmod(5)
dt - (wday.zero? ? 6 : (wday - 1)) + 7*weeks + days
end
The variable wday is assigned to the day of week for the start date, dt. The start date is moved back to the previous Monday, unless it falls on a Monday, in which case it is not changed. That is reflected in the expression
wday.zero? ? 6 : (wday - 1)
which is subtracted from dt. The number of week days is correspondingly adjusted to
week_days + { 0=>4, 6=>4 }.fetch(wday, wday-1)
The remaining calculations are straightforward.
def display(start_str, week_days)
start = Date.parse(start_str)
7.times.map { |i| start + i }.each do |ds|
de = given_date_plus_week_days(ds, week_days)
puts "#{ds.strftime("%a, %b %d, %Y")} + #{week_days} -> #{de.strftime("%a, %b %d, %Y")}"
end
end
display("April 8", 15)
Mon, Apr 08, 2019 + 15 -> Mon, Apr 29, 2019
Tue, Apr 09, 2019 + 15 -> Tue, Apr 30, 2019
Wed, Apr 10, 2019 + 15 -> Wed, May 01, 2019
Thu, Apr 11, 2019 + 15 -> Thu, May 02, 2019
Fri, Apr 12, 2019 + 15 -> Fri, May 03, 2019
Sat, Apr 13, 2019 + 15 -> Fri, May 03, 2019
Sun, Apr 14, 2019 + 15 -> Fri, May 03, 2019
display("April 8", 17)
Mon, Apr 08, 2019 + 17 -> Wed, May 01, 2019
Tue, Apr 09, 2019 + 17 -> Thu, May 02, 2019
Wed, Apr 10, 2019 + 17 -> Fri, May 03, 2019
Thu, Apr 11, 2019 + 17 -> Mon, May 06, 2019
Fri, Apr 12, 2019 + 17 -> Tue, May 07, 2019
Sat, Apr 13, 2019 + 17 -> Tue, May 07, 2019
Sun, Apr 14, 2019 + 17 -> Tue, May 07, 2019
Never tried Go before and currently doing a small project. One of the task is to get current system time and represent it in YYYY-MM-DDT00:00:00Z format. I believe that Z means that time is represented in UTC format but when i looked into db, all timestamps are like this i.e., 2011-11-22T15:22:10Z.
So how can i format like this in Go?
Update
I was able to format it using following code
t := time.Now()
fmt.Println(t.Format("2006-01-02T15:04:05Z"))
Now the question remains, what Z signifies here. Should i get UTC Time?
Another question, it looks like that the value i am using to format impacts the output i.e., when i used 2019-01-02T15:04:05Z the output became 2029-02-02T20:45:11Z, why?
Go provides very flexible way to parse the time by example. For this, you have to write the "reference" time in the format of your choice. The reference time is Mon Jan 2 15:04:05 MST 2006. In my case, I used this reference time to parse the Now():
fmt.Println(time.Now().UTC().Format(time.RFC3339))
There are also other reference types if you want to see:
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Or you can use you desired reference.
"If a time is in Coordinated Universal Time (UTC), a "Z" is added directly after the time without a separating space. "Z" is the zone designator for the zero UTC offset. "09:30 UTC" is therefore represented as "09:30Z" or "0930Z". Likewise, "14:45:15 UTC" is written as "14:45:15Z" or "144515Z".[16]"
From https://en.wikipedia.org/wiki/Time_zone#UTC
// Some valid layouts are invalid time values for time.Parse, due to formats
// such as _ for space padding and Z for zone information.
and
// Replacing the sign in the format with a Z triggers
// the ISO 8601 behavior of printing Z instead of an
// offset for the UTC zone. Thus:
// Z0700 Z or ±hhmm
// Z07:00 Z or ±hh:mm
// Z07 Z or ±hh
From the source for package time/format.go
I have successfully created a DST method called dst_datechange that takes a date, is parsed out using Time.parse. It looks like this:
require 'time'
def dst_datechange(date)
date = Time.parse(date.to_s) # if date.class.eql?(String)
case
when (date > Time.parse('March 11, 2018 2:00am')) && (date <
Time.parse('November 4, 2018 2:00am'))
date = Time.parse('November 4, 2018 2:00am')
puts "the date rounded to november 4, 2018"
when (date > Time.parse('November 4 2018, 2:00am')) && (date <
Time.parse('March 10, 2:00am'))
date = Time.parse('March 10, 2019 2:00am')
puts "the date rounded to march 10 2019"
when (date > Time.parse('March 10, 2019 2:00am')) && (date <
Time.parse('November 3, 2019 2:00am'))
date = Time.parse('November 3, 2019 2:00am')
when (date > Time.parse('November 3, 2019 2:00am')) && (date <
Time.parse('March 8, 2020 2:00am'))
date = Time.parse('March 8, 2020 2:00am')
when (date > Time.parse('March 8, 2020 2:00am')) && (date <
Time.parse('November 1, 2020 2:00am'))
date = Time.parse ('November 1, 2020 2:00am')
else
raise "The date #{date} does not match any dst date parameter"
end
date
puts "the new DST date is #{date}"
end
and my "puts" displays this...
the date rounded to: november 4, 2018
the new DST date is now: 2018-11-04 02:00:00 -0600
Now that I am receiving the correct date, I have a step that takes that dst_datechange and performs a subtraction, however, I am getting an error that says:
TypeError: no implicit conversion of Integer into Array
I am not sure what I am doing wrong but I know its most likely a formatting issue where I am trying to subtract a date time object with just a time object. here is my step below where the stacktrace is pointing the failure at:
date = (dst_datechange(Time.now) - (60*60*3))
puts "the date is now adjusted 3 hours back from 2:00am: #{date} "
end
I am unsure how to format that (60*60*3) to subtract 3 hours from that new November 2018-11-04 02:00:00 -0600 date and basically roll it back to 2018-11-03 23:00:00 -0600
Your method def dst_datechange(date) doesn't return the date you want it to, but instead puts your string.
When you call that in your second part, dst_datechange(Time.now), that doesn't return the date, but the return value for the last puts.
Try calling 'date' again after your final puts in your dst_datechange method:
when (date > Time.parse('March 8, 2020 2:00am')) && (date < Time.parse('November 1, 2020 2:00am'))
date = Time.parse ('November 1, 2020 2:00am')
else
raise "The date #{date} does not match any dst date parameter"
end
puts "the new DST date is #{date}"
date
end
You need to specify that you want to subtract hours. Try:
(Time.now - 3.hours).to_datetime
Or, if using ActiveSupport you can specify that you want three hours ago:
3.hours.ago
Since 2007, in most jurisdictions in the United States and Canada, Daylight Saving Time ("DST") has begun at 2:00am on the second Sunday of March, and ended at 2:00am on the first Sunday in November. In Mexico, DST begins at 2:00am on the first Sunday in April and ends at 2:00am on the last Sunday in October. The experience varies in other parts of the world.1
Given a Time object (possibly computed from a string representation of a time) your code returns a second Time object equal to the time at which the next time change occurs, from DST to STD or vice-versa (i.e., in those parts of the United States and Canada that have adopted DST). There is no need to hard-wire those dates. The calculation can be done as follows.
require 'time'
def dst_datechange(time)
year = time.year
if time.dst?
start_std(year)
else
year += 1 if time >= Time.new(year, 11)
start_dst(year)
end
end
def start_std(year)
date = Date.new(year, 11)
date += (7-date.wday) % 7
Time.new(date.year, date.month, date.day, 2)
end
def start_dst(year)
date = Date.new(year, 3, 8)
date += (7-date.wday) % 7
Time.new(date.year, date.month, date.day, 2)
end
['June 17, 2018 1:00pm', 'November 4, 2018 12:59am', 'November 4, 2018 1:00am',
'March 10, 2019 1:59am', 'March 10, 2019 2:00am'].
each do |s|
t = DateTime.strptime(s, '%B %e, %Y %l:%M%P').to_time
t = Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec)
puts "#{s}: #{ dst_datechange(t) }"
end
June 17, 2018 1:00pm: 2018-11-04 02:00:00 -0800
November 4, 2018 12:59am: 2018-11-04 02:00:00 -0800
November 4, 2018 1:00am: 2019-03-10 03:00:00 -0700
March 10, 2019 1:59am: 2019-03-10 03:00:00 -0700
March 10, 2019 2:00am: 2019-11-03 02:00:00 -0800
Notice that the first, second and last examples return a time whose hour is 2. This is in fact one hour after the time changed. The other two examples return an hour of 3, which is an instant after the time changed. Note:
Time.new(2019, 3, 10, 2)
#=> 2019-03-10 03:00:00 -0700
Time.parse('March 10, 2019 2:00am')
#=> 2019-03-10 03:00:00 -0700
In future, DST date ranges could change (as they did in 2007) or DST could be eliminated altogether. In production code, therefore, it would be prudent to address these possibilities. Assuming the method Time#dst? would continue to exist, Time.new(year,6).dst? should tell us if we still have DST, and if so, one could search day-by-day to see when the time changes occur.
1. Source
Simple question, but I can't find a good or definitive answer. What is the best and most efficient way to combine Ruby Date and Time objects (objects, not strings) into a single DateTime object?
I found this, but it's not as elegant you would hope:
d = Date.new(2012, 8, 29)
t = Time.now
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec, t.zone)
By the way, the ruby Time object also stores a year, month, and day, so you would be throwing that away when you create the DateTime.
When using seconds_since_midnight, changes in daylight savings time can lead to unexpected results.
Time.zone = 'America/Chicago'
t = Time.zone.parse('07:00').seconds_since_midnight.seconds
d1 = Time.zone.parse('2016-11-06').to_date # Fall back
d2 = Time.zone.parse('2016-11-07').to_date # Normal day
d3 = Time.zone.parse('2017-03-12').to_date # Spring forward
d1 + t
#=> Sun, 06 Nov 2016 06:00:00 CST -06:00
d2 + t
#=> Mon, 07 Nov 2016 07:00:00 CST -06:00
d3 + t
#=> Sun, 12 Mar 2017 08:00:00 CDT -05:00
Here's an alternative, similar to #selva-raj's answer above, using string interpolation, strftime, and parse. %F is equal to %Y-%m-%d and %T is equal to %H:%M:%S.
Time.zone = 'America/Chicago'
t = Time.zone.parse('07:00')
d1 = Time.zone.parse('2016-11-06').to_date # Fall back
d2 = Time.zone.parse('2016-11-07').to_date # Normal day
d3 = Time.zone.parse('2017-03-12').to_date # Spring forward
Time.zone.parse("#{d1.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 06 Nov 2016 07:00:00 CST -06:00
Time.zone.parse("#{d2.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 07 Nov 2016 07:00:00 CST -06:00
Time.zone.parse("#{d3.strftime('%F')} #{t.strftime('%T')}")
#=> Sun, 12 Mar 2017 07:00:00 CDT -05:00
Simple:
Date.new(2015, 2, 10).to_datetime + Time.parse("16:30").seconds_since_midnight.seconds
# => Object: Tue, 10 Feb 2015 16:30:00 +0000
You gotta love Ruby!
If using Rails, try any of these:
d = Date.new(2014, 3, 1)
t = Time.parse("16:30")
dt = d + t.seconds_since_midnight.seconds
# => ActiveSupport::TimeWithZone
dt = (d + t.seconds_since_midnight.seconds).to_datetime
# => DateTime
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec)
# => DateTime
If you are using Ruby on Rails, this works great.
I built a method to extend the DateTime class to combine a date and a time. It takes the zone from the date so that it does not end up an hour off with daylight savings time.
Also, for convenience, I like being able to pass in strings as well.
class DateTime
def self.combine(d, t)
# pass in a date and time or strings
d = Date.parse(d) if d.is_a? String
t = Time.zone.parse(t) if t.is_a? String
# + 12 hours to make sure we are in the right zone
# (eg. PST and PDT switch at 2am)
zone = (Time.zone.parse(d.strftime("%Y-%m-%d")) + 12.hours ).zone
new(d.year, d.month, d.day, t.hour, t.min, t.sec, zone)
end
end
So you can do:
DateTime.combine(3.weeks.ago, "9am")
or
DateTime.combine("2015-3-26", Time.current)
etc...
I found another way, I hope this is correct.
datetojoin=Time.parse(datetime).strftime("%Y-%m-%d")
timetojoin=Time.parse(time).strftime("%T")
joined_datetime = Time.parse(datetojoin +" "+ timetojoin).strftime("%F %T")
Any thoughts? Please share.