I have made a huge mistake.
Initially I created my model with a field called start_date and made it a string to keep track of event dates.
Now I'm realizing it would be nice to have this field as a date type so I could do calculations like find events where start_date is between today and 1 month from now.
This issue is I already have 500 records so starting over would suck....
The format of the start_date field is in a rails compatible type " 2011-02-21 22:00:00 " but its just a string...
Is there anything I can do?
Create a migration to add a start_date_2 column of the type you want
Model.find(:all).each { |i| i.update_attributes(:start_date_2, Date.new(i.start_date)) }
Create a migration to delete start_date and to rename start_date_2 to start_date
This should work, out of the top of my head.
You could try just doing an EXPORT on the table (making sure to only export data, do not include CREATE and/or DROP table commands).
Create a migration to change the datatype
TRUNCATE the table
IMPORT the data
Since the column is now a date field, it should parse the input of a string just fine, considering that's what you provide it anyway
Perhaps, you can do away with the risk of changing column type if there is live data. The parse methods can save you. From Ruby-doc:
parse(str='-4712-01-01', comp=true, sg=ITALY)
Create a new Date object by parsing from a String, without specifying the format.
str is a String holding a date representation. comp specifies whether to interpret 2-digit years as 19XX (>= 69) or 20XX (< 69); the default is not to. The method will attempt to parse a date from the String using various heuristics; see _parse in date/format.rb for more details. If parsing fails, an ArgumentError will be raised.
Here and here are some more examples / explanations. Hope this helps.
Related
I have a model with :birth_date of type date.
I've tried to put a string like 3 janvier 1968 (French language) into that field and somehow in database I saw that PostgreSQL or someone else converted it into a date!
I also tried some other dates like 3 février 1968 or like 3 fevrier 1968 which didn't work and turned out to be NULL in db.
I can't find information about this feature anywhere. How does this work?
Rails knows that attribute is a Date from the database definition, so it converts the string you give it to a Date. If you create a new instance of your model in the Rails console and assign to birth_date, you can show that it's already a Date even before you save it to the database:
m = Model.new # Use your model name
m.birth_date = "3 février 1968"
m.birth_date.class
The console should tell you that m.birth_date is a Date.
So the conversion to Date is done before you save the model to the database. Rails defines a String::to_date method that calls the Ruby ::Date.parse method, which converts various human-readable date strings into a Date (https://ruby-doc.org/stdlib-2.3.1/libdoc/date/rdoc/Date.html#method-c-parse). In the Rails source, you'll see that whatever you assign to a Date attribute is converted to a Date with the to_date method. So when you assign a String, it happens via String::to_date which calls Date.parse.
As you mentioned in your comment, Date.parse seems to take a fairly loose approach to the months when they're spelled out. I tried a variety of English, French, and Spanish months in Date.parse, and as long as the first three letters of the non-English month are the same as the English month, Date.parse will convert them. But if the first three letters are different, then Date.parse throws an error.
if you have a column in the database as type 'date', it will only save as a date. Rails does it's best to convert a string into a recognized date if possible. You should always pass the 'birth_date' data as a date (i.e. use a date_field). Otherwise, if you REALLY want to store it as a string, the birth_date column must be of type string in the database
I am using RoR with MSSQL server as database, in a table I am saving date with 'date' datatype.
RoR saving the date correctly e.g if I am saving 2012-10-20 then it is saving 2012-10-20 but when I display it on front-hand it display like 2012-10-02 for 2013-10-20, 2012-10-01 for 2013-10-10, 2012-10-01 for 2013-10-15 etc.
What is going wrong... I can't figure it out
Edit
I am not asking for date formating technique. The issue is that date not fetched correctly as it saved in database, if I used datatime datatype instead of date datatype then all goes right.
You should do:
<%= #user.created_at.strftime("%Y-%m-%d") %>
Or if you want it to be more readable then:
<%= #user.created_at.to_date %>
You can try both which ever you like
EDIT
You have to do like mentioned above otherwise you have to create a new attribute to store date only. created_at is default timestamp type See this link. You can use any of both ways either convert created_at to date or introduce new column to table
How are you displaying it on your view?
For example the following would show "January 2010"
<%= #user.created_at.strftime("%B %Y") %>
You probably want year, month, date? So %Y %m %d
According to the github page of the adapter:
Date/Time Data Type Hinting
SQL Server 2005 does not include a native data type for just date or
time, it only has datetime. To pass the ActiveRecord tests we
implemented two simple class methods that can teach your models to
coerce column information to be cast correctly. Simply pass a list of
symbols to either the coerce_sqlserver_date or coerce_sqlserver_time
methods that correspond to 'datetime' columns that need to be cast
correctly.
class Topic < ActiveRecord::Base
coerce_sqlserver_date :last_read
coerce_sqlserver_time :bonus_time
end
This should point you in the right direction
I have a date of birth column on my user table that takes a DATE. As this datatype appears as YYYY-MM-DD, I assume that when inputting a date to the database it must have the format, for example: 2013-12-26.
I have seen methods on StackOverflow for creating a random DateTime in Ruby, such as here. However, after much searching I can't find a way to generate a random date without the time, for example in the past 100 years, and have it properly formatted for the DATE datatype. In Rails, what is the best way to generate a random date without the time?
This seems to work:
def rand_date(days)
date = Date.today-rand(days)
date.to_s(:db)
end
But is there a more elegant solution that comes with Rails? I am new to Rails and programming, so any assistance would be most helpful!
Your method is correct. If you are using Rails, there are some trivial improvements such as
def rand_date(days)
rand(days).days.ago(Date.today)
end
which is mostly equivalent to
def rand_date(days)
rand(days).days.ago.to_date
end
The second version is less efficient because it creates more Date/Time objects during the internal conversions.
Apply to_s(:db) if you need the Date to be formatted as String.
A different approach would require you to construct a date passing the result of a rand to Date.new.
This is in core ruby:
1 #!usr/bin/ruby
2
3 require 'date'.
4
5 10.times do |t|
6 random_year = Random.new.rand(2000..2014) # custom range for years
7 random_month =Random.new.rand(1..12)
8 random_day = Random.new.rand(1..30)
9 puts "#{Date.new(random_year,random_month,random_day)}"
10 end
2014-11-29
2010-10-20
2006-02-23
2009-09-17
2006-01-14
2009-01-06
2002-07-06
2005-11-05
2013-06-20
2005-12-02
Here is something I used to generate random birth dates when populating a customer database. It works on days, and in this example, gives random dates between 1967-01-09 and 1993-01-12 by using the Date#jd method:
Date.jd(2439500 + rand(9500))
You can twiddle the dates generated by setting the base (in this case 2439500, which is 1967-01-09) and the random number to increase or decrease the range of dates produced.
Example:
irb(main):043:0> 10.times { puts Date.jd(2439500 + rand(9500)) }
1973-06-07
1973-11-09
1983-07-27
1990-11-03
1967-06-18
1967-06-20
1970-07-28
1990-05-13
1986-11-26
1989-02-15
I'm currently given three values in a table
A date value in the format of %dd-%mname-%yy (i.e 06-may-05), and am parsing that using Date.parse(input,true) to fix the issue with the leading values.
I'm then given a time value in the form of %hh:%mm:%ss.%ms (the ms of which I can take or leave) and a third value of a GMT offset.
I can't really see anyway to convert these three values into a single DateTime object that would allow me to manipulate it using the range of ruby tools without first parsing the second value to time, somehow changing the offset ((given as a + or - n value) as in +2 or -6)to a signed int and then applying it and then parsing this all to a super dateTime object.
There's got to be a better way. Is there?
Chronic may be able to parse this (if you concatenate everything in one string, maybe with some modifications) but I haven't checked.
Okay in order to create a dateTime value with the time and the date given and to take into account an offset you need the following code
d = DateTime.parse(dateVal+" "+TimeVal)
offset = Rational(offset_val,24)
d = d.new_offset(offset)
So take your date, given to you as say 05 May 2010 and a timeval in the form hh:mm:ss
With an offset of +- any value, for this instance say -8
Then this code will generate you a new date object, offset to the amount you require
I'm trying to run the following db command against Informix:
delete from table1
where u_id in (select u_id
from table2
where c_id in (select c_id
from ptable
where name = 'Smith'
and dob = '29-08-1946'));
I pass this in as a string to the db.ExecuteNonQuery method in the MS Data Application block and I get the above error?
To get the date format '29-08-1946' to work, you need your DBDATE environment variable set to a value such as "DMY4-" (or "DMY4/"). These are standard variations for the UK (I used them for years; I now use "Y4MD-" exclusively, which matches both ISO 8601:2004 (Date formats) and ISO 9075 (SQL), except when debugging someone else's environment). There are other environment variables that can affect date formatting - quite a lot of them, in fact - but DBDATE takes priority over the others, so it is the big sledgehammer that fixes the problem.
One of the problems is that your notation using a plain string is not portable between US and UK (and ISO) settings of DBDATE. If you have a choice, the neutral constructor for dates is the MDY() function:
WHERE dob = MDY(8,29,1946)
This works regardless of the setting of DBDATE. You can probably use TO_DATE() too:
SELECT TO_DATE('29-08-1946', '%d-%m-%Y') FROM dual;
This generated '1946-08-29 00:00:00.00000' for me - the function generates a DATETIME YEAR TO FRACTION(5) value, but those convert reliably to DATE values in Informix.
You can also use the DATE() function or an explicit cast to DATE (either CAST('29-08-1946' AS DATE) or '29-08-1946'::DATE), but both of those are subject to the whims of the locale of the users.
Your date field is improperly formatted. Since there is no 29th month in the year 1946 that is what is causing the error.
I'd try just swapping the month and day. 08-29-1946.
The way the day and month parts of a date string are read in can depend on your computer's culture settings.
It is always safer to pass date strings to a database in the form 'dd-MMM-yyyy' (i.e. '29-aug-1946')
It's even safer to pass them as YYYY-MM-DD, the dd-MMM-yyyy in that example will fail on a server with a (for example) French locale.