I have a rails and react app and i noticed i have been logging the date into my backend as day/month/year instead of month/day/year. what is the best way to go into my rails backend and fix theses dates. For example I want to turn "7/3/2018" into "3/7/2018" (yes they are strings).
I'm assuming i would start off with something like this:
date = "7/3/2018"
date.split("/")
but then how will i swap the values? Or is there a better way to do this other than to use split?
You can get each value in the array from the splitted string, and then interpolate them in a new string in the order you need:
date = '7/3/2018'
month, day, year = date.split('/')
p "#{day}/#{month}/#{year}" # "3/7/2018"
Other way could be using Date#parse and strftime to handle the format output:
require 'date'
date = '7/3/2018'
p Date.parse(date).strftime('%m/%d/%Y') # "03/07/2018"
Related
I want to get a flat array of dates in a date range for Items with many Bookings. A Booking has :start_date and :end_date.
example, Item has these bookings:
Booking A: 10/1/17 to 10/3/17
Booking B: 11/2/17 to 11/4/17
I tried using pluck. Item.bookings.pluck[:start_date, :end_date] and it gives me an array that looks like this [["10,01,17", "10,03,17"], ["11,02,17" , "11,04,17" ]]
What I need is a flat array with the date ranges like this ["10,01,17", "10/02/17", "10,03,17", "11,02,17" , "11,03,17", "11/04/17"]
Well, in order to get ranges, you need actual Date objects. To get those out of strings like yours, you'll need to use Date.strptime. Then you can build Ranges out of the date pairs, and then convert back to strings with Date#strftime:
require 'date'
format = '%m/%d/%y' # mm/dd/yy; adjust as needed
dates = Item.bookings.pluck(%i<start_date end_date>).map do |bounds|
Range.new(*bounds.map { |d| Date.strptime(d, format) }).map do |d|
d.strftime(format)
end
end.flatten
Which with your example data set gives me this:
["10/01/17", "10/02/17", "10/03/17", "11/02/17", "11/03/17", "11/04/17"]
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'd like to mimic the functionality of the Mac calendar quick event or Fantastical's quick entry. Using the Chronic gem, I can pass a string like:
"Today at 3pm"
=> 2014-01-24 15:00:00 -0600
Chronic parsing doesn't work if you pass in something like:
"Eat at Joes Today at 3pm"
=> nil
What I've done so far is use a simple regex to split a string at a word normally used to return a date with Chronic. The initial regex is simple:
scan(/(.+)(tomorrow{1}.+|in\s.+|next\s.+|today\s.+)/)
This returns an array with the "title", if you will, and the string I want to sent to Chronic to parse for me.
Two questions:
Is this really the best way to do this? I'd have to provide some mega regex to split whatever string I think my users will submit here.
Would hacking at Chronic be better? It's already parsing the dates for me, but my initial thought is no because if you pass Eat at Joes Today at 3pm to Chronic.parse, it'll return nil. It seems it doesn't recognize the part of the string for formatting the date in it's present form.
I wouldn't edit Chronic. Chronic's only function is to parse natural language date time, not other input. You might be interested in the Nickel gem here:
https://github.com/iainbeeston/nickel
This separates time from other language.
n = Nickel.parse("use the force on july 1st at 9am", Time.now)
n.message #=> "use the force"
n.occurrences.first.start_date #=> "20110701"
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 using Rails and MongoMapper as my working platform.
I want to generate a custom key with the help of month and year. The possible format would be YYYYMM####,
YYYY is current YEAR which I can get as Date.today.strftime("%Y")
MM is current Month Which I can get as Date.tody.strftime("%m")
After that ### is incremented integer value
I get the last job with the code
jobForLastnum = Job.last(:order => :_id.desc)
lastJobNum = jobForLastnum.job_number
Now my question is I received the job_number as '201305100'
I want to split it with custom length like, ['2013','05','100']
I know how to split a string in ruby and I successfully did that but i got result as individual character like
['2','0','1','3','0','5','1','0','0']
With the help of this I could retrieve the year:
lastJobNum.to_s[0,4]
With the help of this I got the month:
lastJobNum.to_s[4,2]
But after that there is custom length string. How can I get all the data in a single array?
You can simply use ranges:
c = "2013121003"
[c[0..3], c[4..5], c[6..-1]]
You can also use String#unpack:
"20131210034".unpack("A4A2A*")
Or with regexp as suggested by tessi, using String#scan:
c = "2013121003"
c.scan(/(\d{4})(\d{2})(\d+)/)
In all cases, this will return an array with the year, month, and job id as strings.
A regexp can help you here.
jobNumber = 201305100
year, month, job_id = jobNumber.to_s.match(/(\d{4})(\d{2})(\d*)/)[1..3]
First, we convert the jobNumber to a String. Then we throw a regexp at it. The regexp has three capture groups ((\d{4}) four numbers for the year, (\d{2}) two numbers for the month, (\d*) any remaining number for the job_id).
The job_number.to_s.match(...) returns a MatchData object, which we can access by its first three capture groups with [1..3] (see the documentation).
Finally, we assign the resulting Array to our variables year, month, and job_id.
year
#=> 2013
month
#=> 05
job_id
#=> 100