File.(filename).mtime the same output format like Date.today (ruby) - ruby

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

Related

Ruby 2.3.1 Date.parse returns another date when separator is space char

Just got this today with my ruby console:
$ irb
2.3.1 :001 > require 'date'
=> true
2.3.1 :002 > Date.parse '30/08/2016'
=> #<Date: 2016-08-30 ((2457631j,0s,0n),+0s,2299161j)>
2.3.1 :003 > Date.parse '30 08 2016'
=> #<Date: 2016-09-30 ((2457662j,0s,0n),+0s,2299161j)>
2.3.1 :004 >
Separating with spaces (dates were formatted like this on a spreadsheet from work...dont ask why..hehe), it gave me a date one month after!!
What am I missing? Or shouldn't I expect a correct date, because I'm passing an invalid format anyway?
Use Date.strptime instead, it can take a template to parse the input
i.e.
Date.strptime('30 08 2016', '%d %m %Y')
=> #<Date: 2016-08-30 ((2457631j,0s,0n),+0s,2299161j)>
Just re-iterating my comments, it looks like Date.parse ignores the input after first space and just uses current month and year.
Date.parse '01 01 2015'
=> #<Date: 2016-10-01 ((2457663j,0s,0n),+0s,2299161j)>
Funnily enough spaces are fine if you spell the month.
Date.parse '01 jan 2015'
=> #<Date: 2015-01-01 ((2457024j,0s,0n),+0s,2299161j)>

Oj Time dump - differences in linux and windows

I have a time stamp I am obtaining from an Access database. Unfortunately, the timestamp represents the time only, but is stored as 1899-12-30 13:05:00 +0000. The date part of it is in a different field. I need to preserve the data as much as possible while I am storing it in a json blob.
I am using Oj (which is wonderful) to dump the data to json. I have encountered the following behavior on the Windows platform:
irb(main):001:0> require 'oj'
=> true
irb(main):002:0> t = Time.new(1899,12,30,13,5,0) #this is my actual timestamp
=> 1899-12-30 13:05:00 +0000
irb(main):003:0> Oj.dump(t)
RangeError: bignum too big to convert into `long'
from (irb):3:in `dump'
from (irb):3
from C:/RailsInstaller/Ruby2.2.0/bin/irb:11:in `<main>'
irb(main):004:0>
Now, on linux:
2.3.0 :001 > require 'oj'
=> true
2.3.0 :002 > t = Time.new(1899,12,30,13,5,0)
=> 1899-12-30 13:05:00 +0000
2.3.0 :003 > Oj.dump(t)
=> "{\"^t\":-2209114500.000000000e0}"
I need to make this work on Windows because my source database is MS Access. Please help.
Time is not handled properly, but you can convert to float. The result string differ a bit from your original:
irb(main):001:0> require 'oj'
=> true
irb(main):002:0> t = Time.new(1899,12,30,13,5,0)
=> 1899-12-30 13:05:00 +0100
irb(main):003:0> Oj.dump(t)
RangeError: bignum too big to convert into `long'
from (irb):3:in `dump'
from (irb):3
from C:/Ruby23-x64/bin/irb.cmd:19:in `<main>'
irb(main):005:0> Oj.dump(t.to_f)
=> "-2209118100.0"
Or if you need the exact response you can use an array:
irb(main):001:0> require 'oj'
=> true
irb(main):002:0> t = Time.new(1899,12,30,13,5,0)
=> 1899-12-30 13:05:00 +0100
irb(main):012:0> A1 = Array.new(1)
=> [nil]
irb(main):017:0> A1[0] = '^t'
=> "^t"
irb(main):028:0> A1[1] = t.to_f
=> "-2209118100.0"
irb(main):035:0> Oj.dump(A1).tr("[","{").tr("]","}")
=> "{\"^t\",\"-2209118100.0\"}"

I am trying to convert UTC datetime to a specific timezone in ruby

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"

Rubygems Chronic cannot parse "2010-09-12 3:12pm" but can parse "2010-09-12 3pm" or "last monday 3:12pm"?

It seems strange that "2010--9-12 3:12pm" is a weak spot of Chronic Rubygem? Is there a way to make it work? (or another gem that can do it?) I also hope to find a parser that can handle 2010-09-12 3:12pm UTC or other timezones such as PDT, PST, or UTC+8 or -0700
irb(main):001:0> RUBY_VERSION
=> "1.8.7"
irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'chronic'
=> true
irb(main):004:0> Chronic.parse('9/12/2010')
=> Sun Sep 12 12:00:00 -0700 2010
irb(main):005:0> Chronic.parse('9/12/2010 3pm')
=> Sun Sep 12 15:00:00 -0700 2010
irb(main):006:0> Chronic.parse('9/12/2010 3:12pm') # <-- cannot work
=> nil
irb(main):007:0> Chronic.parse('last monday 3:12pm')
=> Mon Sep 06 15:12:00 -0700 2010
irb(main):008:0> Chronic.parse('2010-09-12')
=> Sun Sep 12 12:00:00 -0700 2010
irb(main):009:0> Chronic.parse('2010-09-12 3:12pm') # <-- cannot work
=> nil
It works for me using latest Chronic on Github on Ruby 1.8.7 (2009-06-12 patchlevel 174):
>> RUBY_VERSION
=> "1.8.7"
>> require './chronic/lib/chronic'
=> true
>> Chronic.parse('9/12/2010 3:12pm')
=> Sun Sep 12 15:12:00 +0100 2010
>> Chronic.parse('2010-09-12 3:12pm')
=> Sun Sep 12 15:12:00 +0100 2010
In the test suite there are tests for:
time = parse_now("2006-08-20 7pm")
assert_equal Time.local(2006, 8, 20, 19), time
time = parse_now("2006-08-20 03:00")
assert_equal Time.local(2006, 8, 20, 3), time
But not exact match to your problem date(s). So if you have discovered a bug then it might be worth telling Chronic's author so that he can update the tests.
BTW... what do you get when you try:
require 'time'
puts Time.parse('2010-09-12 3:12pm')
Because I get the correct: Sun Sep 12 15:12:00 +0100 2010 (NB. I'm in day light saving time here). I mention this because I saw a ambiguous tweet this morning about problem with time API in a minor point release.
/I3az/

Is there an add_days in ruby datetime?

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

Resources