Rails 3 Activerecord TimeWithZone to String without offset - ruby-on-rails

I have:
irb(main):016:0> t[0].change_date
=> Tue, 08 May 2012 18:33:53 FET +03:00
irb(main):017:0> t[0].change_date.class
=> ActiveSupport::TimeWithZone
irb(main):018:0> t[0].change_date.to_s
=> "2012-05-08 18:33:53 +0300"
How Can I get a string representation of datetime but without offset +3000? I need only "2012-05-08
18:33:53"

You can use strftime to format the way you would like to view the datetime.
The strftime documentation.
So, in your case, if you would like to see the date as: 2012-05-08 18:33:53, then use:
t[0].change_date.strftime("%Y-%m-%d %H:%M:%S")

You can use the helper method in ActiveSupport like
t[0].change_date.to_formatted_s(:db)
As the to_fomatted_s is aliased to_s you can also use
t[0].change_date.to_s(:db)
You can check support for time formats in the documentation date format (http://api.rubyonrails.org/classes/Date.html#DATE_FORMATS)

Related

Different outcomes using include? and between? for same date range Rails 5

Why do I get different outcomes in these two queries?
Query 1 = false (creating array of shift IDs then checking if shift ID is in array):
shifts = Shift.where('date_time BETWEEN ? AND ?', Time.zone.now - 3.hours, Time.zone.now + 24.hours).pluck(:id)
shifts.include?(16923) # false
Query 2 = true (checking if shift date_time is between a time range):
Shift.find(16923).date_time.between?(Time.zone.now - 3.hours, Time.zone.now + 24.hours) # true
The attribute date_time is a string, can that have anything to do with it?
At the time of writing, here are the current results:
Shift.find(16923).date_time = "2018-09-01T07:45:00+00:00"
Time.zone.now - 3.hours = Fri, 31 Aug 2018 13:34:07 BST +01:00
Time.zone.now + 24.hours = Sat, 01 Sep 2018 16:35:22 BST +01:00
Looks to me that it's between those two ranges, so why is it not included in the first array?
date_time is a String or a DateTime object? that may be the problem.
Because both String and Datetime objects accept a between? method, both inherited at the end from Comparable https://apidock.com/ruby/Comparable/between%3F
A String will be compared alfabethically
'11'.between?('0','2') # => true
A DateTime object will call between? on a Time objects which is represented as an integer and it's compared ordinally
11.between?(0,2) # => false
If date_time is a String, I'd suggest to change it to a DATETIME column type, it makes more sense semantically. If you can't change it, you can add a custom getter to return a DateTime object parsing the string.
def date_time
DateTime.parse(self[:date_time])
end
I'm not that familliar with SQL operators and it's optimizations, but I'm guessing it is comparring both ordinally, that's would explain why the query works and not the between? method. Still I can't confirm this, I'm just guessing (maybe it even depends on the implementation and the table engine, I don't know).

Parsing date using strftime

I have a problem parsing dates taken in from scraping a website using Nokogiri. I scrape the datetime using
#date = h4.at('time[itemprop="startDate"]')[:datetime]
This gives me 2015-04-28 19:30:00 UTC, which is inserted into my date column, of type "datetime".
Using strptime I am trying to parse the date into a "dd/mm" format, and enter it into my Rails table:
Date.strptime(#date, "%Y-%m-%d %H:%M:%S %Z").strftime("%m/%d/%Y")
#event=Event.new
#event.date= #date
Any help would be very much appreciated.
Here's some code that might help:
require 'date'
require 'time'
date = Date.strptime('2015-04-28 19:30:00 UTC', "%Y-%m-%d %H:%M:%S %Z")
# => #<Date: 2015-04-28 ((2457141j,0s,0n),+0s,2299161j)>
date.strftime('%m/%d/%y')
# => "04/28/15"
Parsing into a Date object stores only the year, month and day information.
datetime = DateTime.strptime('2015-04-28 19:30:00 UTC', "%Y-%m-%d %H:%M:%S %Z")
# => #<DateTime: 2015-04-28T19:30:00+00:00 ((2457141j,70200s,0n),+0s,2299161j)>
datetime.strftime('%m/%d/%y')
# => "04/28/15"
time = Time.strptime('2015-04-28 19:30:00 UTC', "%Y-%m-%d %H:%M:%S %Z")
# => 2015-04-28 19:30:00 UTC
time.strftime('%m/%d/%y')
# => "04/28/15"
Parsing into a DateTime, or Time object captures all the information.
The error you're seeing is often caused by a date string in a format you don't expect. That often happens when you expect a value in 'mm/dd/yy' order, but actually receive one in 'dd/mm/yy' order. This happens because the US uses 'mm/dd/yy' and most of the rest of the world uses 'dd/mm/yy':
date = Date.strptime('2015-28-04', '%Y-%m-%d')
# ~> -:7:in `strptime': invalid date (ArgumentError)
or
date = Date.strptime('28-04-2015', '%m-%d-%Y')
# ~> -:7:in `strptime': invalid date (ArgumentError)
You can work around that by using some rescue statements to try several different formats.
You don't want to use parse because it'll assume 'dd/mm/yyyy' and will blow up with US dates, and is slower because it tries multiple formats before giving up. So, using fixed formats you expect is the way to go but you need to search for your various formats of date/datetime strings you'll expect to find and write format strings to match. And, since you're scraping pages, it's possible to find a LOT of bad/malformed values so program defensively.
You don't need strftime and you can parse the date with parse. Just convert the string to a Date object and assign that to your ActiveRecord attribute:
#event = Event.new
#event.date = Date.parse('2015-04-28 19:30:00 UTC')

Ruby on Rails invalid date error when parsing datetime string to convert to a different format

In my Rails App (Rails 2.3.14 and Ruby 1.8.7) I am trying to convert a datetime string into a different format to perform a search on my MySQL database but I am getting an invalid date error and I can't seem to figure out why, I've read a good few similar questions but I still can't seem to resolve the issue.
# check if filter contains a time stamp
if params[:sSearch].include?('/') and params[:sSearch].include?(':')
datetime = DateTime.strptime(params[:sSearch], "%Y-%m-%d %H:%M")
params[:sSearch] = datetime
end
Example scenario
04/11/13 16:14
should convert to
2013-11-04 16:14
I thought it might have been to do with the fact that the seconds aren't included in the front-end representation of the string as the precise datetime in the database table is 2013-11-04 16:14:52 so I included the seconds now but still getting the same error and I don't think that should matter since I am using the LIKE operand with wildcards on either side of the search term, so even without the seconds it should work.
You should use slashes in the format and replace %Y (four digit year) with %y (abbreviated two digit year) to get the desired result. Besides, the order of the date fields is reversed. The correct format would be:
"%d/%m/%y %H:%M"
I think you confused the purpose of strptime and strftime. Whereas the p in strptime stands for "parse" (make DateTime from String), the f in strftime stands for "format" (the other direction).
require 'date'
DateTime.strptime("04/11/13 16:14", "%Y-%m-%d %H:%M")
# ArgumentError: invalid date
DateTime.strptime("04/11/13 16:14", "%d/%m/%Y %H:%M")
#=> #<DateTime: 0013-11-04T16:14:00+00:00 ((1722836j,58440s,0n),+0s,2299161j)>
# Wrong! You do not want the year 0013, but 2013
DateTime.strptime("04/11/13 16:14", "%d/%m/%y %H:%M")
#=> #<DateTime: 2004-11-13T16:14:00+00:00 ((2453323j,58440s,0n),+0s,2299161j)>
# Correct
you can later convert it to the desired format with DateTime#strftime like this:
# parse the user input to a DateTime object
datetime = DateTime.strptime("04/11/13 16:14", "%d/%m/%y %H:%M")
# reformat it
params[:sSearch] = datetime.strftime("%Y-%m-%d %H:%M")
strptime converts the given string into a datetime object using the format given.
DateTime.strptime("04/11/13 16:14", "%m/%d/%y %H:%M").strftime("%Y-%m-%d %H:%M")
There is a problem with your template, try: DateTime.strptime("04/11/13 16:14", "%d/%m/%y %H:%M")

Rails ActiveRecord date parsing for i18n (specifically european date formats)

I'm working on a rails project for an Australian website. As a result, they want to be able to enter date formats in the more european-standard of 'dd/mm/yyyy' rather than the US-centric 'mm/dd/yyyy'. I have an ActiveRecord model with a Date field. I'm using jQuery's datepicker to provide the date select on a text field, and have it setting the date to a proper format. But, when I try to save the record, it gets the date wrong. Even when I've set the custom date formats in an intializer according to the i18n guide.
>> b = BlogPost.new
>> b.posted_on = '20/07/2010'
=> "20/07/2010"
>> b.posted_on
=> nil
>> b.posted_on = '07/20/2010'
=> Tue, 20 Jul 2010
It seems that Rails is just using Date.parse to convert the string into a Date object. Is there any way to fix this for the whole project? I don't want to have to write custom code for each model.
class Date
class << self
def _parse_with_us_format(date, *args)
if date =~ %r{^(\d+)/(\d+)/(\d+)$}
_parse_without_us_format("#{$3.length == 2 ? "20#{$3}" : $3}-#{$1}-#{$2}", *args)
else
_parse_without_us_format(date, *args)
end
end
alias_method_chain :_parse, :us_format
end
end
Try to change the default date format (in config/environment.rb)
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.
merge!(default => '%d/%m/%Y %H:%M')
Find out more here http://blog.nominet.org.uk/tech/2007/06/14/date-and-time-formating-issues-in-ruby-on-rails/

Converting twitter post dates to datetime in rails

I am trying to convert the twitter post dates into datetime objects but for some reason they are not converting correctly. If I do this:
d = '12:06 AM Oct 15th'
and
d = DateTime.parse(d)
or
Tweet.new :body => "test", :created_at => d
then the date ends up Sun Nov 15 00:06:00 -0500 2009. All dates are converting and containing the month of November. Am I totally missing something?
DateTime.parse expects the passed in string to be in a standard format. Since that is not the case with your strings, you'll have to use DateTime.strptime and pass it your string representation of date/time, along with the corresponding format string. In your case something like this should work:
d = DateTime.strptime '12:06 AM Oct 15th', '%H:%M %p %b %d'
d.to_s # => "2009-10-15T00:06:00+00:00"
You can check the documentation to see what each of the formatting directions means.
Always always always use the Chronic gem. Will solve all your problems when it comes to date/time parsing: http://github.com/mojombo/chronic
You might be able to get away with mangling it slightly and then using the parser:
s = '12:06 AM Oct 15th'
d = DateTime.parse(s.sub(/(\w\w\w) /, '\1'))
puts d.to_s
# => 2009-10-15T00:06:00+00:00

Resources