Mysql2 throws errors on invalid dates - ruby

I have an issue with Mysql2 when it tries to get an invalid date (e.g. 2012-00-25).
For example:
require 'mysql2'
db = Mysql2::Client.new(....)
results = db.query(query)
results.each do |row|
..
..
end
If the first record has an invalid date, mysql2 will throw an error and it will stop in that point.
How could I handle it correctly (to catch the error and recover the wrong data)?
I don't have control of the source data.
Thanks in advance,
My solution:
I solved the issue adding :cast => false and parsing the date column
db.query(query,:cast => false)
results.each do |row|
..
begin
Date.parse(time)
rescue
# if date is wrong then set the date field
time = "1900-01-01 00:00:00"
end
..
end

Related

Date validation for invalid years

I am trying to do what feels like something quite basic, but struggling. I want to be able to determine if a date is valid, if it is, parse it and output in a formatted string, else return 'bad date'. This is where I have got so far;
require 'date'
date_last_printed = current_item.getProperties['Last Printed']
begin
d = DateTime.parse(date_last_printed.to_s)
if Date.valid_date?(d.year, d.month, d.day)
d.strftime("%d/%m/%Y %H:%M:%S")
else
'bad date'
end
rescue Exception => ex
ex.message
end
However 01/01/1601 is returning as a valid date.
How can I adjust my snippet to return only valid dates (on or after the start of Unix epoch time).
you could perform epoch conversion inside the begin statement.
begin
raise if (t=Time.parse(date_last_printed)).to_i < 0
t.strftime("%d/%m/%Y %H:%M:%S")
rescue
'bad date'
end

ArgumentError: invalid strptime format - `%m/%d/%y' work around

I am in the process of working with an sftp import bug in which I'm trying to flag any dates that are imported that are incorrect. There are two types of dates that could be off. The first is when the year is in the future, or way in the past; the second is when the actual months and days are too high. (Example, 13/20/1995, or 11/35/2000)
I'm using strptime and for dates that are off, flagging them and displaying them as a specific message. The problem I'm running into is that with the strptime format that I'm using, the errors happen right before I sub in the error message.
table_birth_dates = self.class.connection.execute("SELECT birth_date FROM #{temp_table_name}").values.flatten
table_birth_dates.map! do |date|
birth_date = Date.strptime(date, '%m/%d/%Y')
if birth_date.nil?
month_day_error_message = 'Invalid Month/Day'
elsif birth_date > Time.zone.today
future_error_message = 'Year in Future'
elsif birth_date.year < 1900
past_error_message = 'Year too old'
else
birth_date
end
end
The error is happening at the birth_date = Date.strptime(date, '%m/%d/%Y')
For a date such as 10/3/1891, it displays them as Sat, 03 Oct 1891.
However, for the messed up dates such as 33/33/2000 it shows me an error (which makes sense) however I was hoping to fix this error in my conditional.
Would anyone know what I could do?
If you want to use strptime your only option really is to rescue the error:
begin
birth_date = Date.strptime(date, '%m/%d/%Y')
rescue ArgumentError => ex
raise ex unless ex.message == 'invalid date'
# handle invalid date
end
You could set date to, e.g., :invalid there and then have date == :invalid in your conditional if you want to keep all the logic there instead of in the rescue itself.

Ruby + ActiveRecord: How to configure a date field resulting in 'yyyy-mm-dd' date format?

I am using ActiveRecord 4.2.4 to work with database.
Some background:
Ruby '1.9.3'
ActiveRecord '4.2.4'
Cucumber '2.1.0'
I am not using Rails.
I recently ran into this issue, the output file that was generated shows:
ROLE | UPDATED_DATE
Teacher | 2016-10-26 09:54:06 UTC
But what do not want '2016-10-26 09:54:06 UTC' in the UPDATED_DATE, I expect only '2016-10-26' to show in the file, like below:
ROLE | UPDATED_DATE
Teacher | 2016-10-26
The UPDATED_DATE column has a type of DATE in the table. I execute the query without converting it to anything. And I am not using Ruby object/model to map the database table, instead I only simply run the SQL and print out the results into a file. Here is what I have in the code:
def initialize
ActiveRecord::Base.time_zone_aware_attributes = false
db_config = DBConfig.get_config_file(DB_CONFIG)
ActiveRecord::Base.establish_connection(
:adapter => db_config['adapter'],
:username => db_config['username'],
:password => db_config['password'],
:database => db_config['database']
)
#connection = ActiveRecord::Base.connection
end
def extract_file
delimiter = '|'
output_file = 'extract.txt'
query = "Select role, UPDATED_DATE from ROLE where USER_ID = 'user1'"
# loop through the result
File.open(output_file, 'w'){|f|
result = #connection.exec_query(query)
result.rows.each do |row|
array << (row.join(delimiter))
if array.length >= 100
f.puts array.join("\n")
array = []
end
end
end
I tried to add the line below:
ActiveRecord::Timestamp.record_timestamps = false
However, I got the following error:
undefined method `record_timestamps=' for ActiveRecord::Timestamp:Module
According to the site:
http://www.rubydoc.info/gems/activerecord/4.2.4/ActiveRecord/Timestamp
Timestamping can be turned off by setting:
config.active_record.record_timestamps = false
Where to configure it? In the config/database.yml file? Please share your solutions.
When you are only interested in the date of the last update and not the time, then there are two option:
Don't use a updated_at timestamp column in your database. Instead use a updated_on date column and Rails magic will do the rest. Or
cast your timestamp to the date data type before writing into the output file. A simple updated_at.to_date will do the job.

Vague SQLite3 Error Youtube queries

I have coded an app in ruby which queries the youtube website for some keywords which are taken from a specific db. After the youtube query is done the resulted videos' id and title are inserted into 2 different dbs. I have run the code and I got this exception:
C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.8-x86-mingw32/lib/sqlite3/database.rb:91:in `initialize': near "'tag:youtube.com,2008:video:3taEuL4EHAg'": syntax error (SQLite3::SQLException)
Is this error caused by invalid characters in my queries? Should the SQLite gem that I used handle these?
If you need the code here it is:
require "sqlite3"
require "youtube_it"
database = SQLite3::Database.new("data.db")
client = YouTubeIt::Client.new(:dev_key =>"myyoutubekey")
result = database.query("SELECT `keyphrase` FROM `keyphrases`")
result.each do |array|
array.each do |result|
results = client.videos_by(:query => "#{result}", :page => 1, :per_page => 10)
results.videos.each do |videoone|
database.query("INSERT OR IGNORE INTO `videos` (videoID,cachedTitle) VALUES ('#{videoone.video_id}','videoone.title')")
rezultat = database.query("SELECT `id` FROM `keyphrases` WHERE `keyphrase` = '#{result}' ")
rezultat.each do |n|
id = n.to_s.delete("[").delete("]").to_i
database.query("INSERT INTO `keyphrase2videos` (keyphraseID,videoID) VALUES ('#{id}','#{videoone.video_id}'")
end
end
end
end
p "Recored Entered"
I was missing a " ) " in the VALUES clause

How to check that date is correct when using date_select

I search a solution for validate user birth date, for example if user try to submit only day and month but he doesn't select year, date will be invalid, but rails don't show any exception or error if year is not set for example but he skip date, and date will not be updated
I found some old answers about the subject, and it seem not to be clear for me. (note i use date_select helper in my view)
I did already a search about date validation but I'm looking for an effective solution that is up to date
i will be thankful for any suggestion. thank you
DateTime.parse(..) will raise an error if the date is not valid:
[1] pry(main)> DateTime.parse("Feb 31, 2013")
ArgumentError: invalid date
from (pry):1:in `parse'
[2] pry(main)> e = begin; DateTime.parse("Feb 31, 2013"); rescue => e; e; end
=> #<ArgumentError: invalid date>
So just capture the error to check for a valid date:
def valid_date?(string)
begin
DateTime.parse(string)
return true
rescue => e
return false
end
end

Resources