Ruby date time parse to get 'th' - ruby-on-rails

I've got date as string '2020-02-10 8,00' which I want to convert into Monday, 10th of February. I'm aware of this old topic however I cannot find (or use) any related information.
All I have is just parsed string to date - Date.parse '2020-02-10 8,00'

You are halfway there! Date.parse '2020-02-10 8,00' produces a ruby Date object, as you have noted. You now have to apply strftime. However strftime doesn't have any ordinalization so that piece has to be done manually.
date = Date.parse('2020-02-10 8,00')
date.strftime("%A, #{date.day.ordinalize} of %B") #=> Monday, 10th of February
the ordinalize method is provided by ActiveSupport.
If this format will be used multiple times in your app, you may wish to add an app-wide format:
# in config/initializers/time_formats.rb
Date::DATE_FORMATS(:ordinalized_day) = lambda{|date| date.strftime("%A, #{date.day.ordinalize} of %B")}
# anywhere in the app
Date.today.to_formatted_s(:ordinalized_day)

Related

How to get the date by day of the week ruby

I'm creating rails app, and I need to put calendar into it. I have a json data which sending to app once in a week. JSON object has something like this:
route: "Monday"
or
route: "Saturday"
I need to put this day of the week as usual date(date calculated every week, since the day when the JSON was sent), for example JSON objects sent today, and to all of them I should give a date, routes: "Saturday" should give me 24-June-2017. Hope u understand my question :)
To get the current day in Rails, you can use:
Date.today
To get the previous Saturday (since today is Monday 3rd July, that's Saturday 1st July), you can use:
Date.today.beginning_of_week(:saturday)
Or, if what you actually wanted was the previous week's Saturday (Saturday 24th June), then you can use:
Date.today.weeks_ago(1).beginning_of_week(:saturday)
Or, if you prefer:
1.week.ago.beginning_of_week(:saturday)
...However, note that the above will return an ActiveSupport::TimeWithZone object rather than a Date object - so will behave slightly differently.
Have a read through the rails documentation - in particular, the ActiveSupport extensions to ruby's Date class to see what methods are available.
If, for some reason, you needed to do this in pure ruby (i.e. without the above mentioned ActiveSupport extensions that come bundled with rails), then you could instead utilise the Date.parse method:
require 'date'
Date.parse("Saturday") - 7
# => Sat, 01 Jul 2017
In order to convert your Date (or similar) object to the string format you desire ("24-June-2017"), you can use ruby's strftime method:
(Date.parse("Saturday") - 7).strftime('%d-%B-%Y')
In rails, it is a common convention to place such custom date formats in a locale or initializer to avoid repetition. You can then reference this format by name:
# config/initializers/date_formats.rb
# (Call this whatever you want!)
Date::DATE_FORMATS[:calendar] = '%d-%B-%Y'
# Anywhere else in the rails app
Date.today.beginning_of_week(:saturday).to_s(:calendar)
# => "01-July-2017"
In addition to #TomLord answer:
One can check which day of the week it is, by using dedicated method monday? to saturday?
e.g:
Date.today
# => Mon, 03 Jul 2017
Date.today.monday?
# => True
Date.today.saturday?
# => False
When working with any built in packages in Ruby it is always a good idea to check out the documentation for available functions and examples. For time, Ruby comes with a convenient Time object which simplifies much of the interactions we do with Time.
For example, one can get the current time using:
t = Time.now, one can then do (t + 1.days).monday? or (t + 2.days).day == 1.
Days already have corresponding int values.
http://ruby-doc.org/core-2.4.1/Time.html
This documentation applies to the newest head, but you can find the version for your ruby with ruby -v and find the appropriate version because it does change over versions.
For your issue, you could have the URL use the string Monday and using a switch case or hash to derive the integer difference from today, using this one could get the exact calendar date. Once it is parsed to Time, you could also do Time.monday?..Time.sunday?, which you may or may not find useful when trying to solve your problem. There are many ways to approach it, but difference from Today is a good solution and with how Time is able to add days like Time.now + 7.days, it feels natural using Ruby to do it in this way.

Retrieve Hash values with key in a specific date format

I'm using Rails. I've stored a count by month in a postgres db as a hash using hstore.
The stored hash is formatted as follows:
{"2017-03-01 00:00:00 UTC"=>"10", "2017-04-01 00:00:00 UTC"=>"3"}
I'm struggling to find a great way to retrieve specific month counts from this hash due to the date format used for the key.
QUESTION
What is the best way to format a string to match the current hash key date format?
For example for March in the Hash the key is "2017-03-01 00:00:00 UTC"
However, a new DateTime for March 1 2017 is formatted as "2017-03-01T00:00:00+00:00"
Or is it best to change the format of how I am storing the hash in the first place?
If you need a timestamp in a specific format, the standard tool to use is DateTime#strftime (all the time-ish classes will have a strftime method and they all behave the same). In your case:
some_datetime.utc.strftime('%Y-%m-%d %H:%M:%S %Z')
And hooking that up to ActiveRecord:
Model.where('your_hstore -> :key', :key => some_datetime.utc.strftime('%Y-%m-%d %H:%M:%S %Z'))
Or:
Model.where('your_hstore -> ?', some_datetime.utc.strftime('%Y-%m-%d %H:%M:%S %Z'))
%Z should be the "Time zone abbreviation name" and for me it produces strings like 'UTC', 'PDT', ... If your strftime (which almost certainly is just a wrapper around the system's libc version of strftime) doesn't produce the strings that you want then you have some options:
Drop the timezone completely if it will always be UTC. Then the keys would look like 2017-03-01 00:00:00 and you'd use '%Y-%m-%d %H:%M:%S' as your strftime format string.
If they keys are actually just dates as they appear to be, then use dates and drop the time-of-day. Then your keys would look like 2017-03-01, you'd use Date instances in Ruby rather than DateTimes, and you'd say some_date.strftime('%Y-%m-%d') or some_date.iso8601 in Ruby to get your hstore keys.
If you are using non-UTC timezones, then convert everything to UTC and go with 1 or 2.
If you don't want any of the above, switch to numeric timezone offsets (2017-05-10 18:05:57 +0000, 2017-05-10 18:06:48 +00:00, ...) and use %z, %:z, or %::z in the strftime format string (see the docs for difference between these three).
These of course require reworking any data you already have in the database but it is best to get the out of the way sooner rather than later.

Ruby - I need to convert string into a timestamp

I need to convert a string that represents a date to a timestamp object in Ruby.
For example:
date_string = "18-Feb-2016 09:01:04"
convert to a timestamp like so
2016-02-18 14:01:04
I need to save this to a mysql database were the column is type timestamp.
I have researched this for most of the day and can not find a solution. I know you can use Time.parse but that includes timezone and DateTime.parse().to_time includes the timezone. Since it has to be a timestamp i can not use strftime method.
I need the time to be included because it will be used for calculation purposes.
Any help would be greatly appreciated.
Thank you
TL;DR
datetime = DateTime.parse("18-Feb-2016 09:01:04").to_s(:db)
returns
"2016-02-18 09:01:04"
Here's a quick explanation...
1. Convert your string to a Date object with DateTime.parse
You can use the .parse method from the Date or DateTime class in order to parse a string. The parse method will return a Date object like this:
$ DateTime.parse("18-Feb-2016 09:01:04")
$ => #<DateTime: 2016-02-18T09:01:04+00:00 ((2457437j,32464s,0n),+0s,2299161j)>
.parse is a method provided by Ruby.
2. Format the string with DateTime.parse.to_s
Ruby on Rails gives you access to the DateTime.to_formatted_s method to change the formatting of the Date object prior to storing it in your database.
To match the format that you specified:
$ datetime = DateTime.parse("18-Feb-2016 09:01:04").to_formatted_s
Note: to_s is aliased from to_formatted_s and to_formatted_s is a method provided by Rails, not Ruby.
Use to_datetime method in Rails.
"12-10-2015".to_datetime
=> Mon, 12 Oct 2015 10:36:00 +0000
http://apidock.com/rails/String/to_datetime
Edited to add precise answer.
You can use .to_time or .to_datetime, the .to_time returns the date and time with timezone but the .to_datetime returns full date with week name but it shows +0000 as timezone, you will see the difference in both the formats, see the following example.
# used .to_time
"18-Feb-2016 09:01:04".to_time
## Output
2016-02-18 09:01:04 +0530
# used .to_datetime
"18-Feb-2016 09:01:04".to_datetime
## Output
Thu, 18 Feb 2016 09:01:04 +0000
I've interpreted the question to be that you wish to convert the string "18-Feb-2016 09:01:04" to the string "2016-02-18 14:01:04" (generalized to arbitrary date-time strings, of course).
Let:
str = "18-Feb-2016 09:01:04"
What you want is done in two steps. The first is to convert this string to a DateTime object, that is, an instance of the class DateTime. The second step is to construct the desired string from the DateTime object.
One way to create the DateTime object is to use the method DateTime::parse:
require 'date'
DateTime.parse(str)
#=> #<DateTime: 2016-02-18T09:01:04+00:00 ((2457437j,32464s,0n),+0s,2299161j)>
That works fine for the string format you gave, but can be problematic with other formats. For example:
DateTime.parse "4-5-16 09:01:04"
#=> #<DateTime: 2004-05-16T09:01:04+00:00 ((2453142j,32464s,0n),+0s,2299161j)>
As long as you know the format that will be used, it's generally better to use DateTime#strptime with the appropriate pattern comprised of format directives:
pattern = "%d-%m-%y %H:%M:%S"
DateTime.strptime("4-5-16 09:01:04", pattern)
#=> #<DateTime: 2016-05-04T09:01:04+00:00((2457513j,32464s,0n),+0s,2299161j)>
See DateTime#strftime for the format directives.
For the problem at hand:
dt = DateTime.strptime(str, "%d-%b-%Y %H:%M:%S")
#=> #<DateTime: 2016-02-18T09:01:04+00:00 ((2457437j,32464s,0n),+0s,2299161j)>
The second step is to construct the desired string with the above-referenced strftime method:
dt.strftime("%Y-%m-%d %H:%M:%S")
#=> "2016-02-18 09:01:04"

Ruby: get TimeZone component of string

I'm working with Date strings in Ruby and want to determine if a string was passed with a timezone or not (beyond simply parsing the text). If no timezone is supplied, I want to convert it to a certain timezone dependent on other factors.
Example:
DateTime.parse("2014-01-01T23:59:00")
=> #<DateTime: 2014-01-01T23:59:00+00:00 ((2456659j,86340s,0n),+0s,2299161j)>
DateTime.parse("2014-01-01T23:59:00Z")
=> #<DateTime: 2014-01-01T23:59:00+00:00 ((2456659j,86340s,0n),+0s,2299161j)>
DateTime.parse("2014-01-01T23:59:00PST")
=> #<DateTime: 2014-01-01T23:59:00-08:00 ((2456660j,28740s,0n),-28800s,2299161j)>
The problem is that parsing "2014-01-01T23:59:00" and "2014-01-01T23:59:00Z" (with Zulu) yields the same result, when one is specifying "Zulu" and the other isn't. I'm sure the default behavior is to assume UTC if no zone is supplied.
To check that the date string doesn't end with a time zone, you can check that the minutes and seconds are the end of the string, using this regex: \d{2}:\d{2}$
Here are some examples using debuggex to illustrate:
\d{2}:\d{2}$
Debuggex Demo

Date conversion in rails

I am importing data from CSV inside Rails 3.2 and saving it to mongodb collection and everything works fine except the date field. The imported date format is DD/MM/YYY. Please how can I convert the imported date to YYYY-MM-DD?
Thanks
You could use date parsing like this:
Date.strptime('01/02/2003', '%d/%m/%Y').to_s #=> "2003-02-01"
Date.strptime creates a Date object from a string in the given format
Date#to_s returns it in the ISO 8601 format (i.e. YYYY-MM-DD)
But it depends on how big your CSV is - this would create a bunch of intermediate Date objects which would be a bit slower than a (slightly ugly) string indexing approach:
def reformat_date(date)
"#{date[6..9]}-#{date[3..4]}-#{date[0..1]}"
end
reformat_date('01/02/2003') #=> "2003-02-01"
Update
I was curious so I ran some quick benchmarks - the date parsing method was about 2.7 times slower than the string method (5.289s vs 1.981s for a million conversions, Ruby 1.9.3/Windows). YMMV.
You may need
require 'date'
Then use the following statement to parse the date:
d = Date.strptime('09/10/2012', '%d/%m/%Y')
Using the following examples will return the right format:
d.year #=> 2012
d.mon #=> 10
d.day #=> 9
d.strftime('%Y/%m/%d') #=> "2012/10/09"
Then save it to the database. I'm not familiar with mongodb, though, but I'm sure you know what to do.
For more information on date parsing you should visit http://www.ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/DateTime.html.

Resources