Rails datetime format "dd/mm/yyyy" - ruby-on-rails

I receive dates like "14/04/17 07:00"
I want to get only the date like this: 14/04/2017
And only the hour 07:00
I tried this way, BTW I know it's for US time, it render me 17/04/10
DateTime.parse(datetime).strftime("%d/%m/%Y")
Humm I can't find anywhere how to do this?
Thanks for your help
EDIT
with the suggestion:
my_date = DateTime.parse(datetime).strftime("%d/%m/%Y")
If I do in my terminal:
[1] pry(main)> O = Onduleur.last
Onduleur Load (0.2ms) SELECT "onduleurs".* FROM "onduleurs" ORDER BY "onduleurs"."id" DESC LIMIT ? [["LIMIT", 1]]
=> #<Onduleur:0x007fa6b70186e0
id: 144,
identifier: 2,
datetime: "11/04/17 23:00",
energy: 0,
created_at: Wed, 12 Apr 2017 15:17:04 UTC +00:00,
updated_at: Wed, 12 Apr 2017 15:17:04 UTC +00:00>
[2] pry(main)> my_date = DateTime.parse(O.datetime).strftime("%d/%m/%Y")
=> "17/04/2011"
[3] pry(main)>

For reading you can use strptime and specify the format:
datetime = "14/04/17 07:00"
DateTime.strptime(datetime, "%d/%m/%y %R")
=> Wed, 14 Apr 0017 07:00:00 +0000
Explanation
%d - Day of the month, zero-padded (01..31)
%m - Month of the year, zero-padded (01..12)
%y - year % 100 (00..99)
%R - 24-hour time (%H:%M)
For getting the date you can transform DateTime objects to Date objects using to_date or use .strftime("%d/%m/%Y") directly on DateTime to get String.
[47] pry(main)> a
=> Fri, 14 Apr 2017 07:00:00 +0000
[48] pry(main)> a.to_date
=> Fri, 14 Apr 2017
[49] pry(main)> a.strftime("%d/%m/%Y")
=> "14/04/2017"
[50] pry(main)> a.strftime("%R")
=> "07:00"
Full docs here. Also a full list of format directives is available on strftime docs

You can set to variables with the desire data
datetime = "2017-04-12 10:30:14"
my_date = DateTime.parse(datetime).strftime("%d/%m/%Y")
my_hour = DateTime.parse(datetime).strftime("%H:%M")
puts my_date
puts my_hour
Output:
12/04/2017
10:30
EDIT:
If you have this format date (11/04/2017 23:00), you can try with .to_time method
require 'active_support/core_ext/string'
datetime2 = "11/04/2017 23:00".to_time
my_date2 = datetime2.strftime("%d/%m/%Y")
my_hour2 = datetime2.strftime("%H:%M")
puts my_date2
puts my_hour2

Related

strftime(%Z) returns wrong result

I have this date
date = Mon, 15 Aug 2016 13:00:00 UTC +00:00
which is ActiveSupport::TimeWithZone class
Then, I need to get the time in time zone "Fiji"
start_in_time_zone = date.in_time_zone("Fiji")
This returns Tue, 16 Aug 2016 01:00:00 +12 +12:00
Then, I need to present the date with the name of the time zone, so
time_zone_abbr = start_in_time_zone.strftime("%Z")
It should return "FJT"
but returns "+12"
Any idea why?
I am using ruby 2.3.7 and rails 4.2.7
UPDATE
If I do
start_in_time_zone = date.in_time_zone("Madrid")
it returns
"CEST"
UPDATE 2
I have tried to see where the problem is by setting different time.
date=Time.utc(2018, 07, 25, 20, 30, 45)
date.class #=> Time
date.in_time_zone("Madrid") #=> Wed, 25 Jul 2018 22:30:45 CEST +02:00
date.in_time_zone("Fiji") #=> Thu, 26 Jul 2018 08:30:45 +12 +12:00
date.in_time_zone("EST") #=> Wed, 25 Jul 2018 15:30:45 EST -05:00
Sadly, it seems there is no 'FJT' abbreviation assigned to 'Fiji' in timezone data used by Rails. Also, support for those abbreviations seems patchy regarding Pacific timezones.
irb(main):002:0> DateTime.now.in_time_zone('Samoa').strftime('%Z')
=> "+13"
irb(main):003:0> DateTime.now.in_time_zone('Midway Island').strftime('%Z')
=> "SST"
irb(main):004:0> DateTime.now.in_time_zone('Samoa').strftime('%Z')
=> "+13"
irb(main):005:0> DateTime.now.in_time_zone('Tokelau Is.').strftime('%Z')
=> "+13"
irb(main):006:0> DateTime.now.in_time_zone('Wellington').strftime('%Z')
=> "NZST"
UTC offset is displayed as fallback. If it's any help, remember that full name and additional information can be retrieved with .time_zone.tzinfo on ActiveSupport::TimeWithZone objects. 'FJ' code is recognized by TZInfo::Country.
irb(main):056:0> TZInfo::Country.get('FJ')
=> #<TZInfo::Country: FJ>
irb(main):057:0> TZInfo::Country.get('FJ').zone_info
=> [#<TZInfo::CountryTimezone: Pacific/Fiji>]

Fix timezone issue with database in Rails on Heroku

My Rails app is hosted on Heroku with a Postgress database. For a certain model I'm asking the user to chose a day and a time, which I combine to a date before saving the model:
def create_timestamp
self.date = day.to_datetime + time.seconds_since_midnight.seconds
end
When I chose for instance today # 20:50:00 and store it in the database, my record looks like this:
<Report id: 1, account_id: 1, date: "2016-11-05 20:50:00", description: "test", created_at: "2016-11-05 19:50:57", updated_at: "2016-11-05 19:50:57", deleted_at: nil, user_id: 1, report_category_id: 2, time: "2000-01-01 20:50:00", day: "2016-11-05">
As you might notice, the created_at date is different, because it's in a different timezone. While the created_at is stored in UTC +0000, my custom date, which uses local timezone is CET +0100.
So when I type in console: Report.find(1).date, it returns 2016-11-05 21:50:00 +0100.
How can I store the correct date in the initial set, or make the database return the correct timezone when querying?
Thanks
What you're doing currently is basically this:
>> date = Date.new(2016, 11, 6)
=> Sun, 06 Nov 2016
>> time = Time.new(2000, 1, 1, 20, 50, 0)
=> 2000-01-01 20:50:00 +0100
>> date.to_datetime + time.seconds_since_midnight.seconds
=> Sun, 06 Nov 2016 20:50:00 +0000
to_datetime converts the time-zone-less Date into a DateTime representing midnight UTC on that date, and then you add 20 hours and 50 minutes.
Instead of midnight UTC, you want midnight in your local time zone as your starting point. So you could do this, for example:
>> date.in_time_zone + time.seconds_since_midnight.seconds
=> Sun, 06 Nov 2016 20:50:00 CET +01:00
Rails should then be smart enough to convert it to UTC when storing in the database and back to CET when retrieving from the database.
To be clear about the difference, compare:
>> date
=> Sun, 06 Nov 2016
>> date.to_datetime
=> Sun, 06 Nov 2016 00:00:00 +0000
>> date.in_time_zone
=> Sun, 06 Nov 2016 00:00:00 CET +01:00
You should use
Time.zone.now
# or
Time.current
Which will return the time in time zone

How to save a date into rails using the console

I have a table that has a date field in it. How would I save the date using the console? I tried
event = Event.create(name:"Concert", date:08/20/2016, location:'Portland', state:'OR')
However, I am getting an Invalid octal digit error.
You'll want to pass in an actual Date object, which you can get from a string with the Date.parse method:
event = Event.create(name: "Concert", date: Date.parse('2016-08-20'), location: 'Portland', state: 'OR')
Note that I've rewritten your date to be in a different format. The MM/DD/YYYY format is not portable across locales, so I'd strongly suggest you use YYYY-MM-DD (the ISO 8601 format).
Using a string in the correct format will do the trick. For example:
>> foo = Foo.create date: "20/8/2016"
(0.0ms) begin transaction
SQL (1.0ms) INSERT INTO "foos" ("date") VALUES (?) [["date", Sat, 20 Aug 2016]]
(0.9ms) commit transaction
#<Foo id: 1, date: "2016-08-20">
>> foo.date
Sat, 20 Aug 2016
ActiveSupport provides core extensions on the String class for conversions from strings to date, time, and datetime. This is probably ok, and more convenient, to take advantage of while testing around in Rails console.
Taking advantage of this extension in the application itself (instead of explicitly parsing with Date.parse) is totally up to you and your team.
From the source:
"1-1-2012".to_date # => Sun, 01 Jan 2012
"01/01/2012".to_date # => Sun, 01 Jan 2012
"2012-12-13".to_date # => Thu, 13 Dec 2012
"12/13/2012".to_date # => ArgumentError: invalid date
Just to be thorough, examples for String#to_time
"13-12-2012".to_time # => 2012-12-13 00:00:00 +0100
"06:12".to_time # => 2012-12-13 06:12:00 +0100
"2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
"2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
"2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
"12/13/2012".to_time # => ArgumentError: argument out of range
And String#to_datetime:
"1-1-2012".to_datetime # => Sun, 01 Jan 2012 00:00:00 +0000
"01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
"2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000
"12/13/2012".to_datetime # => ArgumentError: invalid date
Try this, for example:
date = Date.parse('3rd Feb 2001') ####=> #<Date: 2001-02-03 ...>
Reference: Date class

Rails: DateTime of different time zones

I have a project model with a datetime attribute to define the deadline. The deadlines are of different time zones, and I receive them in a string format like below:
Jan 1st 2013 00:00:00 EST
Feb 9th 2013 23:59:00 PST
I want to store these values in the default UTC format in the database. I've seen that there are many options to parse the time like Time.zone.parse and Time.parse. My question is: what's the best practice to parse the datetime of different time zones? I'm using Rails 3.2.9.
You need not worry about that at all, as long as you set correct timezone in config/application.rb:
config.time_zone = 'UTC'
You just assign the time strings to the attributes, ActiveRecord will convert it correctly.
1.9.3p125 :002 > project.deadline = "Jan 1st 2013 00:00:00 EST"
=> "Jan 1st 2013 00:00:00 EST"
1.9.3p125 :003 > project.deadline
=> Tue, 01 Jan 2013 05:00:00 UTC +00:00
1.9.3p125 :004 > project.deadline = "Feb 9th 2013 23:59:00 PST"
=> "Feb 9th 2013 23:59:00 PST"
1.9.3p125 :005 > project.deadline
=> Sun, 10 Feb 2013 07:59:00 UTC +00:00
ActiveRecord uses Time.zone.parse to parse the strings internally.
When you run Time.parse it will convert the timestamp to your configured timezone in rails. For example, my rails app runs in EST.
[5] pry(main)> Time.parse('Jan 1st 2013 00:00:00 EST')
=> 2013-01-01 00:00:00 -0500
[6] pry(main)> Time.parse('Feb 9th 2013 23:59:00 PST')
=> 2013-02-10 02:59:00 -0500
Notice the +3:00hrs for the PST timestamp used to get the result into my EST timezone.
To get the UTC version of each timestamp, just call utc
[7] pry(main)> Time.parse('Jan 1st 2013 00:00:00 EST').utc
=> 2013-01-01 05:00:00 UTC
[8] pry(main)> Time.parse('Feb 9th 2013 23:59:00 PST').utc
=> 2013-02-10 07:59:00 UTC

Rails: get #beginning_of_day in time zone

I have a default time zone setup for the rails application.
And an instance of the Date object.
How can I get make Date#beginning_of_day to return the beginning of the day in the specified time zone, but not my local timezone.
Is there any other method to get beginning of the day time in the specified timezone for the given date?
date = Date.new(2014,10,29)
zone = ActiveSupport::TimeZone.new('CET')
date.foo(zone) # should return "Wed, 29 Oct 2014 00:00:00 CET +01:00"
zone = ActiveSupport::TimeZone.new('UTC')
date.foo(zone) # should return "Wed, 29 Oct 2014 00:00:00 UTC +00:00"
DateTime.now.in_time_zone(Time.zone).beginning_of_day
time_zone = Time.zone # any time zone really
time_zone.local(date.year, date.month, date.day)
Problem is, Date.beginning_of_day does not honor Time.zone in ActiveSupport 2.3
Compare https://github.com/rails/rails/blob/v2.3.11/activesupport/lib/active_support/core_ext/date/calculations.rb#L64 (AS 2.3)
to https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/calculations.rb#L74
and
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/zones.rb#L7
(AS 3)
Date#beginning_of_day will always return 00:00.
But as I understand you want to know time in other time zone while in current time zone is beginning of the day.
So. Let's find out beginning of the day in your current place. Imagine it is Paris, France:
bd = DateTime.now.in_time_zone('Paris').beginning_of_day
# or just
bd = DateTime.now.in_time_zone(1).beginning_of_day
#=> Thu, 24 Mar 2011 00:00:00 WET +01:00
Now lets found out what time is in Moscow:
moscow_time = bd.in_time_zone("Moscow") # or in_time_zone(3)
#=> Thu, 24 Mar 2011 02:00:00 AST +03:00
london_time = bd.in_time_zone("London")
#=> Wed, 23 Mar 2011 23:00:00 GMT +00:00
kyiv_time = bd.in_time_zone("Kyiv")
#=> Thu, 24 Mar 2011 01:00:00 EET +02:00
For different form now day:
# You even shouldn't call now, because it by default will be 00:00
date = DateTime(2011, 1, 3).in_time_zone("-10")
# or
date = DateTime.new(2011,1,3,0,0,0,"-10")
# and same way as above
moscow_time = date.in_time_zone("Moscow") # or in_time_zone(3)
and converting Date to DateTime
date = Date.new(2011,1,3).to_datetime.change(:offset => "EST")
Going off Peder's answer, here's what I did for the PST time zone:
DateTime.now.in_time_zone("Pacific Time (US & Canada)").beginning_of_day
I know this post is old, but what about:
Time.zone.parse("12am")
may2 = Date.new(2012,5,2)
midnight = Time.zone.local(may2.year,may2.month,may2.day).beginning_of_day
Wed, 02 May 2012 00:00:00 UTC +00:00
midnight = Time.zone.local(may2.year,may2.month,may2.day).in_time_zone("Moscow").beginning_of_day
=> Wed, 02 May 2012 00:00:00 MSK +04:00
midnight = Time.zone.local(may2.year,may2.month,may2.day).in_time_zone("Alaska").beginning_of_day
=> Tue, 01 May 2012 00:00:00 AKDT -08:00
NOTICE, it's the WRONG DAY.
What is needed is a way to construct a TimeWithZone in the correct timezone.
Time.zone="Alaska"
midnight = Time.zone.local(may2.year,may2.month,may2.day)
I really dislike this, because as far as I can see, I've just changed the system notion of what zone I'm in. The idea is to change my database searches to match the zone of the client...
So, I have to save zone and restore it:
foo = Time.zone; Time.zone="Alaska"; midnight = Time.zone.local(may2.year,may2.month,may2.day); Time.zone = foo
It seems like I ought be able to call TimeWithZone.new(), but I didn't figure out how.
ActiveSupport::TimeZone['Europe/London'].parse('30.07.2013') # 2013-07-29 23:00:00 UTC
ActiveSupport::TimeZone['Asia/Magadan'].parse('30.07.2013') # 2013-07-29 12:00:00 UTC
As Leonid Shevtsov mentioned, Date.beginning_of_day does not honor Time.zone in ActiveSupport 2.3
An alternative I used, if your stuck using Rails 4.0 or ActiveSupport 2.3, and you need to use a custom date:
date = Date.new(2014,10,29)
date.to_time.change(hour: 0, min: 0, sec: 0).in_time_zone #.beginning_of_day
date.to_time.change(hour: 23, min: 59, sec: 59).in_time_zone #.end_of_day
Results:
2.0.0-p247 :001 > date = Date.new(2014,10,29)
=> Wed, 29 Oct 2014
2.0.0-p247 :002 > date.to_time.change(hour: 0, min: 0, sec: 0)
=> 2014-10-29 00:00:00 -0500
2.0.0-p247 :003 > date.to_time.change(hour: 0, min: 0, sec: 0).in_time_zone
=> Wed, 29 Oct 2014 05:00:00 UTC +00:00
2.0.0-p247 :004 > date.to_time.change(hour: 23, min: 59, sec: 59)
=> 2014-10-29 23:59:59 -0500
2.0.0-p247 :005 > date.to_time.change(hour: 23, min: 59, sec: 59).in_time_zone
=> Thu, 30 Oct 2014 04:59:59 UTC +00:00
My original failed model scope using .beginning_of_day to .end_of_day failed to work:
scope :on_day, ->(date) { where( created_at: date.beginning_of_day..date.end_of_day ) }
And, this is what fixed it, since I could not upgrade to Rails 4.0
scope :on_day, ->(date) { where( created_at: date.to_time.change(hour: 0, min: 0, sec: 0).in_time_zone..date.to_time.change(hour: 23, min: 59, sec: 59).in_time_zone ) }
Generate new date in a specific time zone
If you would like to get beginning of the day for a specific date (and you know the exact date), then you have to use:
Time.use_zone('London'){ Time.zone.local(2022, 1, 1) }
# => Sat, 01 Jan 2022 00:00:00.000000000 GMT +00:00
It respects seasonal time change:
Time.use_zone('London'){ Time.zone.local(2022, 6, 1) }
# => Wed, 01 Jun 2022 00:00:00.000000000 BST +01:00
Although it is already referred by accepted answer I'd like to add that personally I prefer block notation.
Convert existing and find out what the day it is in another time zone
If you would like to know what day that would be for a specific timestamp/epoch/date that you already have you need to convert your existing date to the proper time zone, which is already referred by Peder's and Tim's answers:
Time.current.in_time_zone('London').beginning_of_day
Be aware, when converting existing date you may end up in another day (1st became 2nd):
Time.use_zone('London'){ Time.zone.local(2022, 6, 1, 23, 0, 0) }.in_time_zone('Tokyo').beginning_of_day
# => Thu, 02 Jun 2022 00:00:00.000000000 JST +09:00
If you are going to convert time, then Time.now or Time.current is indifferent, but I prefer using Time.current as a rule:
Time.now
# => 2022-09-30 15:29:16 +0000
Time.current
=> Fri, 30 Sep 2022 16:29:36.006315710 BST +01:00

Resources