I'm looking for the best way to take a datetime string from MySQL, explode it in Ruby and return the month, date, and year in separate elements.
How is the string formatted? You could just convert the datetime string into a datetime object, and call the instance methods.
require 'time'
x = "2009/04/16 19:52:30" #grab your datetime string from the database and assign it
y = DateTime.strptime(x, "%Y/%m/%d %H:%M:%S") #create a new date object
Then a simple y.day() yields:
y.day() = 16
and y.hour():
y.hour() = 19
FYI never actually used Ruby much, so this is what I got out of playing with the console, so hopefully this helps shed some light.
require 'time'
x = "2009/04/16 19:52:30"
begin
y = Time.parse(x)
[y.year, y.month, y.day] # => [2009, 4, 16]
rescue ArgumentError
puts "cannot parse date: #{x}"
end
Related
I am trying to create a string value that I will ultimately search for as a filename. The format is as follows: "FILE_NAME_NEEDED_PP_YYYYMMDD.TXT" where date stamp will equal actual date.
require 'date'
require 'time'
myDate = time.strftime('%Y%m%d')
staticName = "FILE_NAME_NEEDED_PP_"
staticExt = ".TXT"
fileName = 'staticName' + "#{myDate}" + 'staticExt'
puts fileName
However when I run the above I get "<main>': undefined local variable or method time' for main:Object (NameError)"
You forgot to declare the time variable. One more thing you are not appending staticExt properly. Use the below code
require 'date'
require 'time'
time = Time.now
myDate = time.strftime('%Y%m%d')
staticName = "FILE_NAME_NEEDED_PP_"
staticExt = ".TXT"
fileName = 'staticName' + "#{myDate}" + "#{staticExt}"
puts fileName
Problem
Your posted code has a number of things wrong with it, including:
Incorrect method invocation of Time#strftime.
You need to invoke #strftime on a valid Time, Date, or DateTime object like Time.now.
Unnecessary require statements.
Time is automatically accessible as part of Ruby's core.
Use of fixed strings rather than variables to form a new string.
Single-quoted strings are not variables. You're just appending strings when you call:
'staticName' + Time.now.strftime("%Y%m%d") + 'staticExt'
#=> "staticName20200710staticExt"
Solution
Here's some refactored code that works, using Kernel#sprintf for readability:
date = Time.now.strftime "%Y%m%d"
static_name = "FILE_NAME_NEEDED_PP_"
static_ext = ".TXT"
filename = sprintf "%s%d%s", static_name, date, static_ext
filename
#=> "FILE_NAME_NEEDED_PP_20200710.TXT"
In C# there is a TimeSpan class. It represents a period of time and is returned from many date manipulation options. You can create one and add or subtract from a date etc.
In Ruby and specifically rails there seems to be lots of date and time classes but nothing that represents a span of time?
Ideally I'd like an object that I could use for outputting formatted dates easily enough using the standard date formatting options.
eg.
ts.to_format("%H%M")
Is there such a class?
Even better would be if I could do something like
ts = end_date - start_date
I am aware that subtracting of two dates results in the number of seconds separating said dates and that I could work it all out from that.
You can do something similar like this:
irb(main):001:0> require 'time' => true
irb(main):002:0> initial = Time.now => Tue Jun 19 08:19:56 -0400 2012
irb(main):003:0> later = Time.now => Tue Jun 19 08:20:05 -0400 2012
irb(main):004:0> span = later - initial => 8.393871
irb(main):005:0>
This just returns a time in seconds which isn't all that pretty to look at, you can use the strftime() function to make it look pretty:
irb(main):010:0> Time.at(span).gmtime.strftime("%H:%M:%S") => "00:00:08"
Something like this? https://github.com/abhidsm/time_diff
require 'time_diff'
time_diff_components = Time.diff(start_date_time, end_date_time)
No, it doesn't. You can just add seconds or use advance method.
end_date - start_date will have Float type
In the end I forked the suggestion in #tokland's answer. Not quite sure how to make it a proper gem but it's currently working for me:
Timespan fork of time_diff
Not yet #toxaq... but I've started something!
https://gist.github.com/thatandyrose/6180560
class TimeSpan
attr_accessor :milliseconds
def self.from_milliseconds(milliseconds)
me = TimeSpan.new
me.milliseconds = milliseconds
return me
end
def self.from_seconds(seconds)
TimeSpan.from_milliseconds(seconds.to_d * 1000)
end
def self.from_minutes(minutes)
TimeSpan.from_milliseconds(minutes.to_d * 60000)
end
def self.from_hours(hours)
TimeSpan.from_milliseconds(hours.to_d * 3600000)
end
def self.from_days(days)
TimeSpan.from_milliseconds(days.to_d * 86400000)
end
def self.from_years(years)
TimeSpan.from_days(years.to_d * 365.242)
end
def self.diff(start_date_time, end_date_time)
TimeSpan.from_seconds(end_date_time - start_date_time)
end
def seconds
self.milliseconds.to_d * 0.001
end
def minutes
self.seconds.to_d * 0.0166667
end
def hours
self.minutes.to_d * 0.0166667
end
def days
self.hours.to_d * 0.0416667
end
def years
self.days.to_d * 0.00273791
end
end
I have the model Teacher which has field :teacher_birthday. I get :teacher_birthday from the view (a single textbox). I want to make sure that an input date has a such format - dd.mm.yyyy (i mean i want to be sure, that an input date as 12.24.1991 will not be save in db because such date is wrong) and that this date exists. Also, i want to do this in the MODEL. Is this possible?
Try the chronic gem. It has very flexible date parsing, including what you're looking for:
[11] pry(main)> require 'chronic'
=> true
[12] pry(main)> Chronic.parse('24.12.1991'.gsub('.','-'))
=> 1991-12-24 12:00:00 -0700
Declare the validation method to be called in your model, and then define this method. The following should roughly do what you need:
validate :validate_teacher_birthday
private
def validate_teacher_birthday
errors.add("Teacher birthday", "is invalid.") unless (check_valid_date && valid_date_format)
end
def valid_date_format
self.teacher_birthday.match(/[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]/)
end
def check_valid_date
begin
parts = self.teacher_birthday.split(".") #contains array of the form [day,month,year]
Date.civil(parts[2].to_i,parts[1].to_i,parts[0].to_i)
rescue ArgumentError
#ArgumentError is thrown by the Date.civil method if the date is invalid
false
end
end
I'm parsing some RSS feeds that aggregate what's going on in a given city. I'm only interested in the stuff that is happening today.
At the moment I have this:
require 'rubygems'
require 'rss/1.0'
require 'rss/2.0'
require 'open-uri'
require 'shorturl'
source = "http://rss.feed.com/example.xml"
content = ""
open(source) do |s| content = s.read end
rss = RSS::Parser.parse(content, false)
t = Time.now
day = t.day.to_s
month = t.strftime("%b")
rss.items.each do |rss|
if "#{rss.title}".include?(day)&&(month)
# does stuff with it
end
end
Of course by checking whether the title (that I know contains the date of event in the following format: "(2nd Apr 11)") contains the day and the month (eg. '2' and 'May') I get also info about the events that happen on 12th May, 20th of May and so on. How can I make it foolproof and only get today's events?
Here's a sample title: "Diggin Deeper # The Big Chill House (12th May 11)"
today = Time.now.strftime("%d:%b:%y")
if date_string =~ /(\d*).. (.*?) (\d\d)/
article_date = sprintf("%02i:%s:%s", $1.to_i, $2, $3)
if today == article_date
#this is today
else
#this is not today
end
else
raise("No date found in title.")
end
There could potentially be problems if the title contains other numbers. Does the title have any bounding characters around the date, such as a hyphen before the date or brackets around it? Adding those to the regex could prevent trouble. Could you give us an example title? (An alternative would be to use Time#strftime to create a string which would perfectly match the date as it appears in the title and then just use String#include? with that string, but I don't think there's an elegant way to put the 'th'/'nd'/'rd'/etc on the day.)
Use something like this:
def check_day(date)
t = Time.now
day = t.day.to_s
month = t.strftime("%b")
if date =~ /^#{day}nd\s#{month}\s11/
puts "today!"
else
puts "not today!"
end
end
check_day "3nd May 11" #=> today!
check_day "13nd May 11" #=> not today!
check_day "30nd May 11" #=> not today!
I write my first project wich using Datamapper as ORM, so please be patient. :)
I try to do get String from DateTime field:
Error.first.submitted_at.to_s
=> "2009-08-24T12:13:32+02:00"
Returned String is not good for me. In ActiveRecord I can do something like that:
Error.first.submitted_at.to_s(:only_date)
or any other date formatter. Is somethig similar available in DataMapper or I must to use strftime method?
That's a feature available using AcitveSupport. You can do require 'activesupport' to get it. That might be overkill, though. You could also use #stamp from Facets to do the same thing, but you have to set up the :only_date format:
require 'facets/date'
Date::FORMAT[:only_date] = '%d.%m.%y' # For Date objects
Time::FORMAT[:only_date] = '%d.%m.%y' # For DateTime objects
d = DateTime.now
d.stamp(:only_date) # => "24.08.09"
If you really want to use it with the to_s method, you can do that, too:
require 'facets/date'
Date::FORMAT[:only_date] = '%d.%m.%y' # For Date objects
Time::FORMAT[:only_date] = '%d.%m.%y' # For DateTime objects
class DateTime
alias :default_to_s :to_s
def to_s(format=nil)
if format.nil?
default_to_s
else
stamp format
end
end
end
d = DateTime.now
d.to_s(:only_date) # => "24.08.09"