In C#, There is a method AddDays([number of days]) in DateTime class.
Is there any kind of method like this in ruby?
The Date class provides a + operator that does just that.
>> d = Date.today
=> #<Date: 4910149/2,0,2299161>
>> d.to_s
=> "2009-08-31"
>> (d+3).to_s
=> "2009-09-03"
>>
In Rails there are very useful methods of Fixnum class for this (here n is Fixnum. For example: 1,2,3.... ):
Date.today + n.seconds # you can use 1.second
Date.today + n.minutes # you can use 1.minute
Date.today + n.hours # you can use 1.hour
Date.today + n.days # you can use 1.day
Date.today + n.weeks # you can use 1.week
Date.today + n.months # you can use 1.month
Date.today + n.years # you can use 1.year
These are convenient for Time class too.
PS: require Active Support Core Extensions to use these in Ruby
require 'active_support/core_ext'
I think next_day is more readable than + version.
require 'date'
DateTime.new(2016,5,17)
# => #<DateTime: 2016-05-17T00:00:00+00:00 ((2457526j,0s,0n),+0s,2299161j)>
DateTime.new(2016,5,17).next_day(10)
# => #<DateTime: 2016-05-27T00:00:00+00:00 ((2457536j,0s,0n),+0s,2299161j)>
Date.new(2016,5,17)
# => #<Date: 2016-05-17 ((2457526j,0s,0n),+0s,2299161j)>
Date.new(2016,5,17).next_day(10)
# => #<Date: 2016-05-27 ((2457536j,0s,0n),+0s,2299161j)>
http://ruby-doc.org/stdlib-2.3.1/libdoc/date/rdoc/Date.html#method-i-next_day.
From the Date class:
+(n)
Return a new Date object that is n days later than the current one.
n may be a negative value, in which case the new Date is earlier than the current one; however, #-() might be more intuitive.
If n is not a Numeric, a TypeError will be thrown. In particular, two Dates cannot be added to each other.
Date.new(2001,9,01).next_day(30) # 30 - numbers of day
# => #<Date: 2001-10-01 ...
You can also use the advance (https://apidock.com/rails/DateTime/advance) method. I think it's more legible.
date = Date.today
# => Fri, 25 Oct 2019
date.advance(days: 10)
# => Mon, 04 Nov 2019
time = DateTime.now
# => Fri, 25 Oct 2019 14:32:53 +0200
time.advance(months:1, weeks: 2, days: 2, hours: 6, minutes: 6, seconds: 34)
# => Wed, 11 Dec 2019 20:39:27 +0200
Related
I have date-time represented in string format like below in the input data I'm getting. I need to convert this to epoch time local. How do I go about this ?
example date-time string
str = "Aug 23 2018 03:49:17:017 PM IST"
Maybe this can put you on track.
Please refer to http://ruby-doc.org/stdlib-2.5.0//libdoc/date/rdoc/DateTime.html.
This is a usage example.
require 'date'
str = "Aug 23 2018 03:49:17:017 PM IST"
d = DateTime.strptime(str, '%b %d %Y %I:%M:%S:%L %p %z')
# Maybe you need %e - Day of the month, blank-padded ( 1..31) instead of %d - Day of the month, zero-padded (01..31)
p d.hour # => 15
p d.min # => 49
p d.sec # => 17
p d.second_fraction # => (17/1000)
p d.day # => 23
p d.month # => 8
p d.year # => 2018
p d.zone # => "+05:30"
# this way you can switch timezone
d = d.new_offset('utc')
p d.zone # => "+00:00"
p d.hour # => 10
d = d.new_offset('brt')
p d.hour # => 7
p d.zone # => "-03:00"
# to print back as string, use strftime:
p d.strftime('%Y-%m-%d %I:%M:%S %z') # => "2018-08-23 07:19:17 -0300"
How can i retrieve Retrieve first and last day of the month with Ruby (DateTime)?
I want to create invoices that start the first day and finishes the last day of the month.
Given a year and a month:
year = 2017
month = 5
You can pass these to Date.new along with a day value of 1 and -1 to get the first and last day respectively:
require 'date'
Date.new(year, month, 1) #=> #<Date: 2017-05-01 ...>
Date.new(year, month, -1) #=> #<Date: 2017-05-31 ...>
Use the beginning_of_month and end_of_month methods
irb(main):004:0> n = DateTime.now
=> Wed, 10 May 2017 14:48:01 +0300
irb(main):005:0> n.to_date.beginning_of_month
=> Mon, 01 May 2017
irb(main):006:0> n.to_date.end_of_month
=> Wed, 31 May 2017
dates = ["11/12/08 10:47", "11/12/08 13:23", "11/12/08 13:30",
"11/25/08 19:21", "2/2/09 11:29", "11/12/08 15:00"]
This throws an invalid argument error:
dates.each do |date|
d = Date.parse(date)
d.mon
end
#=> ArgumentError: invalid date
But take the first date in dates and this is the output:
d = Date.parse('11/12/08 10:47')
puts d.mon
#=> #<Date: 2011-12-08 ((2455904j,0s,0n),+0s,2299161j)>
#=> 12 but this should be 11
In the first example why am I getting an invalid ArgumentError?
In example 2, why is the Date object created with the mon and day swapped?
Given your input, Date.parse is parsing your dates assuming they are in the format YY/MM/DD, so when it try to parse 11/25/08 it fails because 25 is not a valid month:
d = Date.parse('11/12/08 10:47')
d.year
# => 2011
d.month
# => 12
d.day
# => 8
Date.parse('11/25/08 19:21')
# ArgumentError: invalid date
Given that your dates are all in the same format, you should use the Date.strptime method instead:
d = Date.strptime('11/12/08 10:47', '%m/%d/%y')
d.year
# => 2008
d.month
# => 11
d.day
# => 12
Date.strptime('11/25/08 19:21', '%m/%d/%y')
# => #<Date: 2008-11-25 ((2454796j,0s,0n),+0s,2299161j)>
Edit Instead of the format string %m/%d/%y the shortcut %D can be used:
Date.strptime('11/25/08 19:21', '%D')
# => #<Date: 2008-11-25 ((2454796j,0s,0n),+0s,2299161j)>
Ruby's Date.parse is expecting either a YYYY-MM-DD (see also ISO8601 for more information) or a DD-MM-YYYY as well but not DD-MM-YY (i.e. 2 digits only for year). The last is treated instead as YY-MM-DD.
I have an XML file which has a datetime value. I loop through the elements and get the attribute value timeutc.
I managed to convert it to local time zone, but what I am trying to do is convert it to any time zone, PST, CST, EST.
$Appointments = '<appointments><appointment timeutc="2013-10-10T06:00:00" /><appointment timeutc="2013-10-10T06:00:00" /><appointment timeutc="2013-10-10T15:00:00" /></appointments>'
index = 0
doc = REXML::Document.new("#{$Appointments}")
doc.elements.each("appointments/appointment") do |element|
index += 1
value = element.attribute("timeutc").value
to_datetime = DateTime.parse(value).to_s
to_UTC = Time.iso8601(to_datetime).to_s
local_time = Time.iso8601(to_datetime).localtime
puts local_time # => 2013-10-09 23:00:00 -0700
puts local_time.strftime("%A") # => Wednesday
puts local_time.strftime("%B") # => October
puts local_time.strftime("%-d") # => 9
puts local_time.strftime("%l") # => 11
puts local_time.strftime("%M") # => 00
puts local_time.strftime("%p") # => PM
end
You could use the in_time_zone method:
For CST:
local_time.in_time_zone('Central Time (US & Canada)')
For PST:
local_time.in_time_zone('Pacific Time (US & Canada)')
For EST:
local_time.in_time_zone('Eastern Time (US & Canada)')
Ruby's support for time zones hasn't been that great (not sure if this has changed with 2.0), hence the various ActiveSupport libs.
Ruby looks to the environment variable TZ to determine what zone to operate in:
irb [1.9.3]$ ENV["TZ"] # Ruby will look elsewhere and see that I'm in NYC
=> nil
irb [1.9.3]$ Time.iso8601 "2013-10-10T06:00:00"
=> 2013-10-10 06:00:00 -0400
irb [1.9.3]$ ENV["TZ"]="America/Los_Angeles"
=> "America/Los_Angeles"
irb [1.9.3]$ Time.now.zone
=> "PDT"
irb [1.9.3]$ Time.iso8601 "2013-10-10T06:00:00"
=> 2013-10-10 06:00:00 -0700
So... while I'd strongly encourage using the active support methods, you could use something like this:
irb [1.9.3]$ def parse_in_zone(date, zone)
1{ old = ENV["TZ"]
1{ ENV["TZ"] = zone
1{ Time.iso8601 date
1{ ensure
1* ENV["TZ"] = old
1{ end
=> nil
irb [1.9.3]$ parse_in_zone "2013-10-10T06:00:00", "America/Los_Angeles"
=> 2013-10-10 06:00:00 -0700
irb [1.9.3]$ parse_in_zone "2013-10-10T06:00:00", "America/New_York"
=> 2013-10-10 06:00:00 -0400
Also note that DateTime.parse(value) is not necessary. It considers the string's zone when parsing the date:
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00:00").zone
=> "+00:00"
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00+04:00").zone
=> "+04:00"
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00+07:00").zone
=> "+07:00"
Note that in your case I don't think the string: 2013-10-10T06:00:00 is a valid iso date/time (extra :00) but it looks like ruby doesn't care:
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00:0000:000000").to_s
=> "2013-10-10T06:00:00+00:00"
I want to subtract the result of File.mtime and Date.today. Time and weekends are ignored. I am after something like
Date.today - File.mtime
File.mtime gives me Fri Oct 08 11:00:18 +1100 2010
and
Date.today 2010-10-11
I thought that to_s() would work for me but File.mtime(filename).to_s gives me the same result like File.mtime(filename)
any idea how I can get the desired date format from File.mtime? And why to_s is not working?
Something like this?
irb(main):001:0> File.mtime("file")
=> 2010-10-08 17:56:10 +0800
irb(main):002:0> File.mtime("file").year
=> 2010
irb(main):003:0> File.mtime("file").month
=> 10
irb(main):004:0> File.mtime("file").day
=> 8
Similarly with Date
irb(main):001:0> require 'date'
=> true
irb(main):002:0> Date.today
=> #<Date: 2010-10-11 (4910961/2,0,2299161)>
irb(main):003:0> Date.today.year
=> 2010
irb(main):004:0> Date.today.month
=> 10
irb(main):005:0> Date.today.day
=> 11
Or you can use strftime
irb(main):001:0> File.mtime("file").strftime("%Y-%m-%d")
=> "2010-10-08"
Try using Time.now and convert to days manually:
age = Time.now - File.mtime(filename)
age_in_days = (age / 24*60*60).to_i