Convert string to datetime ruby on rails - ruby-on-rails

I know this is basic but I've been struggling for a few hours now and I can't seem to apply one of the many ways there are to convert a string to datetime so I can save it in the database in this format 2018-03-16 00:12:17.555372. Thanks ahead
This is the string output in the console.
params[:event][:start_date]
"03/28/2018 1:46 AM"
[EDIT] Following some leads I've come up with smething really dirty maybe someone can help refactor I'm supressing AM or PM because I don't know how to parse that I know it's awfull any help is appreciated!
if !params[:event][:start_date].empty?
start_date = params[:event][:start_date]
start_date = start_date.gsub(/[AMP]/, '').squish
a = start_date.split('/')
tmp = a[0]
a[0] = a[1]
a[1] = tmp
a = a.split(',').join('/')
start_date = Time.parse(a)
end
if !params[:event][:end_date].empty?
end_date = params[:event][:end_date]
end_date = end_date.gsub(/[AMP]/, '').squish
a = end_date.split('/')
tmp = a[0]
a[0] = a[1]
a[1] = tmp
a = a.split(',').join('/')
end_date = Time.parse(a)
end

You can use DateTime to parse the date from a specific format.
if the format you are looking to parse is "03/28/2018 1:46 AM" then you can do this.
date = DateTime.strptime('03/28/2018 1:46 AM', '%m/%d/%Y %I:%M %p')
# date to ISO 8601
puts date.to_time
# output: 2018-03-28 07:16:00 +0530
puts date.strftime("%m/%d/%Y")
# output: 03/28/2018
Date formats:
Date (Year, Month, Day):
%Y - Year with century (can be negative, 4 digits at least)
-0001, 0000, 1995, 2009, 14292, etc.
%m - Month of the year, zero-padded (01..12)
%_m blank-padded ( 1..12)
%-m no-padded (1..12)
%d - Day of the month, zero-padded (01..31)
%-d no-padded (1..31)
Time (Hour, Minute, Second, Subsecond):
%H - Hour of the day, 24-hour clock, zero-padded (00..23)
%k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
%I - Hour of the day, 12-hour clock, zero-padded (01..12)
%l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
%P - Meridian indicator, lowercase (``am'' or ``pm'')
%p - Meridian indicator, uppercase (``AM'' or ``PM'')
%M - Minute of the hour (00..59)
You can refer to all formats here.

You can parse it like so in ruby:
Parses the given representation of date and time, and creates a DateTime object. This method does not function as a validator.
DateTime.parse('2001-02-03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.parse('20010203T040506+0700')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.parse('3rd Feb 2001 04:05:06 PM')
#=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
Not entirely sure if the string you supplied can be parsed, here is the link to the ruby docs on datetimes Docs

Related

Day name with I18n

Without translation, this would get me today's day name:
Date.today.strftime("%A")
How would I localize it?
I.e. "Mardi" if I18n.locale is set to fr.
You probably have in your locale file(s) the following:
# example with fr
fr:
date:
day_names: [Dimanche, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi]
# ^^^^^^^^ a week starts with a Sunday, not a Monday
In order to get today's name, you could do:
week_day = Date.today.wday # Returns the day of week (0-6, Sunday is zero)
I18n.t('date.day_names')[week_day]
or eventually
I18n.l(Date.today, format: '%A')
l Date.today, format: "%A"
Will work if you have the day_names in your translation file.
if you use rails-i18n, you will have the day names and month names already translated, e.g.:
I18n.l(value, format: "le %A %e %B à %-Hh%M")
# le Dimanche 19 Juillet à 21h00

Format the date using Ruby on Rails

The flickr api provides a posted date as unix timestamp one: "The posted date is always passed around as a unix timestamp, which is an unsigned integer specifying the number of seconds since Jan 1st 1970 GMT."
For example, here is the date '1100897479'. How do I format it using Ruby on Rails?
Once you have parsed the timestamp string and have a time object (see other answers for details), you can use Time.to_formatted_s from Rails. It has several formats built in that you can specify with symbols.
Quote:
time = Time.now # => Thu Jan 18 06:10:17 CST 2007
time.to_formatted_s(:time) # => "06:10"
time.to_s(:time) # => "06:10"
time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
time.to_formatted_s(:number) # => "20070118061017"
time.to_formatted_s(:short) # => "18 Jan 06:10"
time.to_formatted_s(:long) # => "January 18, 2007 06:10"
time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
(Time.to_s is an alias)
You can also define your own formats - usually in an initializer (Thanks to Dave Newton for pointing this out). This is how it's done:
# config/initializers/time_formats.rb
Time::DATE_FORMATS[:month_and_year] = "%B %Y"
Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
Here's my go at answering this,
so first you will need to convert the timestamp to an actual Ruby Date/Time. If you receive it just as a string or int from facebook, you will need to do something like this:
my_date = Time.at(timestamp_from_facebook.to_i)
OK, so now assuming you already have your date object...
to_formatted_s is a handy Ruby function that turns dates into formatted strings.
Here are some examples of its usage:
time = Time.now # => Thu Jan 18 06:10:17 CST 2007
time.to_formatted_s(:time) # => "06:10"
time.to_s(:time) # => "06:10"
time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
time.to_formatted_s(:number) # => "20070118061017"
time.to_formatted_s(:short) # => "18 Jan 06:10"
time.to_formatted_s(:long) # => "January 18, 2007 06:10"
time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
As you can see: :db, :number, :short ... are custom date formats.
To add your own custom format, you can create this file: config/initializers/time_formats.rb and add your own formats there, for example here's one:
Date::DATE_FORMATS[:month_day_comma_year] = "%B %e, %Y" # January 28, 2015
Where :month_day_comma_year is your format's name (you can change this to anything you want), and where %B %e, %Y is unix date format.
Here's a quick cheatsheet on unix date syntax, so you can quickly setup your custom format:
From http://linux.die.net/man/3/strftime
%a - The abbreviated weekday name (``Sun'')
%A - The full weekday name (``Sunday'')
%b - The abbreviated month name (``Jan'')
%B - The full month name (``January'')
%c - The preferred local date and time representation
%d - Day of the month (01..31)
%e - Day of the month without leading 0 (1..31)
%g - Year in YY (00-99)
%H - Hour of the day, 24-hour clock (00..23)
%I - Hour of the day, 12-hour clock (01..12)
%j - Day of the year (001..366)
%m - Month of the year (01..12)
%M - Minute of the hour (00..59)
%p - Meridian indicator (``AM'' or ``PM'')
%S - Second of the minute (00..60)
%U - Week number of the current year,
starting with the first Sunday as the first
day of the first week (00..53)
%W - Week number of the current year,
starting with the first Monday as the first
day of the first week (00..53)
%w - Day of the week (Sunday is 0, 0..6)
%x - Preferred representation for the date alone, no time
%X - Preferred representation for the time alone, no date
%y - Year without a century (00..99)
%Y - Year with century
%Z - Time zone name
%% - Literal ``%'' character
t = Time.now
t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003"
t.strftime("at %I:%M%p") #=> "at 08:56AM"
Hope this helped you.
I've also made a github gist of this little guide, in case anyone prefers.
Easiest is to use strftime (docs).
If it's for use on the view side, better to wrap it in a helper, though.
#CMW's answer is bang on the money. I've added this answer as an example of how to configure an initializer so that both Date and Time objects get the formatting
config/initializers/time_formats.rb
date_formats = {
concise: '%d-%b-%Y' # 13-Jan-2014
}
Time::DATE_FORMATS.merge! date_formats
Date::DATE_FORMATS.merge! date_formats
Also the following two commands will iterate through all the DATE_FORMATS in your current environment, and display today's date and time in each format:
Date::DATE_FORMATS.keys.each{|k| puts [k,Date.today.to_formatted_s(k)].join(':- ')}
Time::DATE_FORMATS.keys.each{|k| puts [k,Time.now.to_formatted_s(k)].join(':- ')}
Have a look at localize, or l
eg:
l Time.at(1100897479)
First you will need to convert the timestamp to an actual Ruby Date/Time.
If you receive it just as a string or int from facebook, you will need to do something like this:
my_date = Time.at(timestamp_from_facebook.to_i)
Then to format it nicely in the view, you can just use to_s (for the default formatting):
<%= my_date.to_s %>
Note that if you don't put to_s, it will still be called by default if you use it in a view or in a string e.g. the following will also call to_s on the date:
<%= "Here is a date: #{my_date}" %>
or if you want the date formatted in a specific way (eg using "d/m/Y") - you can use strftime as outlined in the other answer.
Since the timestamps are seconds since the UNIX epoch, you can use DateTime.strptime ("string parse time") with the correct specifier:
Date.strptime('1100897479', '%s')
#=> #<Date: 2004-11-19 ((2453329j,0s,0n),+0s,2299161j)>
Date.strptime('1100897479', '%s').to_s
#=> "2004-11-19"
DateTime.strptime('1100897479', '%s')
#=> #<DateTime: 2004-11-19T20:51:19+00:00 ((2453329j,75079s,0n),+0s,2299161j)>
DateTime.strptime('1100897479', '%s').to_s
#=> "2004-11-19T20:51:19+00:00"
Note that you have to require 'date' for that to work, then you can call it either as Date.strptime (if you only care about the date) or DateTime.strptime (if you want date and time). If you need different formatting, you can call DateTime#strftime (look at strftime.net if you have a hard time with the format strings) on it or use one of the built-in methods like rfc822.

Is there a Ruby 1.8.7 time.strftime %z bug?

I'm having an issue with Ruby 1.8.7 strftime where the %z is returning the local time after i convert the time to UTC.
I'm doing the following:
>> t = Time.now
=> Mon Dec 19 15:20:16 -0800 2011
>> t.strftime("%z")
=> "-0800"
>> t = Time.now.utc
=> Mon Dec 19 23:20:28 UTC 2011
>> t.strftime("%z")
=> "-0800"
Even after I change the time to UTC, the timezone formatted gets defaulted to my local PST -0800.
Is this a known issue? Is there a way around it?
Note that the fine 1.8.7 manual makes no mention of %z:
...
%w - Day of the week (Sunday is 0, 0..6)
%x - Preferred representation for the date alone, no time
%X - Preferred representation for the time alone, no date
%y - Year without a century (00..99)
%Y - Year with century
%Z - Time zone name
%% - Literal ``%'' character
but the 1.9.3 version does have documented support for %z:
Time zone:
%z - Time zone as hour and minute offset from UTC (e.g. +0900)
%:z - hour and minute offset from UTC with a colon (e.g. +09:00)
%::z - hour, minute and second offset from UTC (e.g. +09:00:00)
%Z - Time zone abbreviation name
The fact the %z produces anything at all appears to be an undocumented and possibly accidental implementation detail.
You can use %Z in 1.8.7 and 1.9.3; for example, you get these results in 1.8.7:
>> t = Time.now
=> Mon Dec 19 16:46:06 -0800 2011
>> t.zone
=> "PST"
>> t.strftime('%z %Z')
=> "-0800 PST"
>> t = Time.now.utc
=> Tue Dec 20 00:46:27 UTC 2011
>> t.zone
=> "UTC"
>> t.strftime('%z %Z')
=> "-0800 UTC"
That will give you the timezone as UTC, PST, EDT, and similar common abbreviations. If you want the offset, you should be using gmt_offset in both 1.9.3 and 1.8.7:
>> Time.now.gmt_offset
=> -28800
>> Time.now.utc.gmt_offset
=> 0
Note that gmt_offset gives you the offset in seconds.
Your problem.
ruby-1.9.2-p290 :004 > Time.now.strftime("%z")
=> "-0500"
ruby-1.9.2-p290 :005 > Time.now.utc.strftime("%z")
=> "+0000"

How can i get the current weekday beginning in ruby?

For example today is 28/07/2011
How do i get the weeks first day the monday which is 25/07/2011 in ruby
>> Date.today.beginning_of_week.strftime('%d/%m/%Y')
#=> 25/07/2011
See the Time and Date classes under Rails for more info, and strftime for information on the formatting options.
Without Rails/ActiveSupport:
phrogz$ irb
> require 'date'
> now = Date.today
#=> #<Date: 2011-07-28 (4911541/2,0,2299161)>
> sunday = now - now.wday
#=> #<Date: 2011-07-24 (4911533/2,0,2299161)>
> monday = now - (now.wday - 1) % 7
#=> #<Date: 2011-07-25 (4911535/2,0,2299161)>
> monday.iso8601
#=> "2011-07-25"
> monday.strftime('%d/%m/%Y')
#=> "25/07/2011"
For more, see the Date class in the Standard Library.
Wrapped up as a method:
require 'date'
# For weekdays to start on Monday use 1 for the offset; for Tuesday use 2, etc.
def week_start( date, offset_from_sunday=0 )
date - (date.wday - offset_from_sunday)%7
end
sun = Date.parse '2011-07-24'
week_start(sun,0).strftime('%a, %b-%d') #=> "Sun, Jul-24"
week_start(sun,1).strftime('%a, %b-%d') #=> "Mon, Jul-18"

Convert Ruby Date to Integer

How can I convert a Ruby Date to an integer?
t = Time.now
# => 2010-12-20 11:20:31 -0700
# Seconds since epoch
t.to_i
#=> 1292869231
require 'date'
d = Date.today
#=> #<Date: 2010-12-20 (4911101/2,0,2299161)>
epoch = Date.new(1970,1,1)
#=> #<Date: 1970-01-01 (4881175/2,0,2299161)>
d - epoch
#=> (14963/1)
# Days since epoch
(d - epoch).to_i
#=> 14963
# Seconds since epoch
d.to_time.to_i
#=> 1292828400
Date cannot directly become an integer. Ex:
$ Date.today
=> #<Date: 2017-12-29 ((2458117j,0s,0n),+0s,2299161j)>
$ Date.today.to_i
=> NoMethodError: undefined method 'to_i' for #<Date: 2017-12-29 ((2458117j,0s,0n),+0s,2299161j)>
Your options are either to turn the Date into a time then an Int which will give you the seconds since epoch:
$ Date.today.to_time.to_i
=> 1514523600
Or come up with some other number you want like days since epoch:
$ Date.today.to_time.to_i / (60 * 60 * 24) ### Number of seconds in a day
=> 17529 ### Number of days since epoch
Time.now.to_i
returns seconds since epoch format
Solution for Ruby 1.8 when you have an arbitrary DateTime object:
1.8.7-p374 :001 > require 'date'
=> true
1.8.7-p374 :002 > DateTime.new(2012, 1, 15).strftime('%s')
=> "1326585600"
I had to do it recently and took some time to figure it out but that is how I came across a solution and it may give you some ideas:
require 'date'
today = Date.today
year = today.year
month = today.mon
day = day.mday
year = year.to_s
month = month.to_s
day = day.to_s
if month.length <2
month = "0" + month
end
if day.length <2
day = "0" + day
end
today = year + month + day
today = today.to_i
puts today
At the date of this post, It will put 20191205.
In case the month or day is less than 2 digits it will add a 0 on the left.
I did like this because I had to compare the current date whit some data that came from a DB in this format and as an integer. I hope it helps you.

Resources