I am using Ruby v2.2.3 on Windows 10.
I want to find out who created and who last modified a given file. Is there a way to do this using Ruby?
I don't have access to Windows, but at least on OSX (and I'd assume unix-lik OS's) File.stat and Etc.getpwuid will get you what you want.
> fstat = File.stat('../.bashrc')
=> #<File::Stat
dev=0x1000004,
ino=43746279,
mode=0100644 (file rw-r--r--),
nlink=1,
uid=501 (philip),
gid=20 (staff),
rdev=0x0 (0, 0),
size=1932,
blksize=4096,
blocks=8,
atime=2016-09-29 11:19:45 -0700 (1475173185),
mtime=2016-07-22 10:56:07 -0700 (1469210167),
ctime=2016-07-22 10:56:07 -0700 (1469210167)>
> Etc.getpwuid(fstat.uid)
=> #<struct Etc::Passwd
name="philip",
passwd="********",
uid=501,
gid=20,
gecos="Philip Hallstrom",
dir="/Users/philip",
shell="/bin/bash",
change=0,
uclass="",
expire=0>
Related
I am trying to use the Date.parse method in Ruby but it is returning odd results when I try to parse early historical dates. For example:
Date.parse("16 January 27 BC")
=> #<Date: -0026-01-16 >
This returns the correct year (although it is -26 instead of -27 but that is normal I think).
But when I try:
Date.parse("19 august 1 BC")
=> #<Date: 2000-08-19 >
Here it assumes the year 2000 as a start date. Same thing for later years:
Date.parse("19 August 14")
=> #<Date: 2014-08-19 >
yearninetynine = Date.parse("19 august AD 99")
=> #<Date: 1999-08-19 >
(I have also tried to replace AD with "CE" but that makes no difference)
The year 100 is where it starts to work properly again:
Date.parse("19 august AD 100")
=> #<Date: 0100-08-19 >
To summarize: up to the year 100 it doesn't parse properly and treats it as years occurring in the 1990s and 2000s, negative years are one less than you would intuitively expect, negative years close to 0 are also not parsed properly.
I tried a few other methods like start=Date::ITALY, but these seem to make no difference. Is there a way to make it parse these years properly?
According to the docs that is exactly what the 2nd argument is for.
Date.parse("19 august 99") #=> Thu, 19 Aug 1999
Date.parse("19 august 99", false) #=> Mon, 19 Aug 0099
Ruby correctly parses the first date but the second one is incorrect. Tested with ruby 1.9.3 and 2.1.2.
Any idea how to get it to work consistently? (We are getting in birth dates as 2 digit years)
Date.strptime("10/11/89","%d/%m/%y")
=> Fri, 10 Nov 1989
Date.strptime("15/10/63","%d/%m/%y")
=> Mon, 15 Oct 2063
The strptime method is parsing the text "63" to the year 2063, not 1963 as you want.
This is because the method decides the century by using the POSIX standard.
The chronic gem has a similar issue because it decides the century, though differently.
A solution is to adjust the date:
d = Date.strptime("15/10/63","%d/%m/%y")
if d > Date.today
d = Date.new(d.year - 100, d.month, d.mday)
end
In the comments of this post, Stefan suggests a good one liner:
d = d.prev_year(100) if d > Date.today
If you need speed, you can try optimizing like this:
d <= Date.today || d = d << 1200
When using %y in strptime, the code assumes that values under 68 are considered in the 21st century, as descirbed here:
The year within century (0-99). When a century is not otherwise specified (with a value for %C), values in the range 69-99 refer to years in the twentieth century (1969-1999); values in the range 00-68 refer to years in the twenty-first century (2000-2068).
In the chronic gem, incidentally, the cut-off year is 64:
Chronic.parse('15/10/64')
# => 1964-10-15 12:00:00 +0200
Chronic.parse('15/10/63')
# => 2063-10-15 12:00:00 +0300
Chronic gem has added an extended support parsing 2 digit years with ambiguous_year_future_bias option:
irb(main):029:0> Chronic.parse('15/10/99', ambiguous_year_future_bias: 10)
=> 2099-10-15 12:00:00 +0300
irb(main):030:0> Chronic.parse('15/10/99', ambiguous_year_future_bias: 50)
=> 1999-10-15 12:00:00 +0300
Add the Chronic gem to your Gemfile
gem 'chronic'
Then just parse it:
Chronic.parse("15/10/68")
=> 1968-10-15 12:00:00 -0700
ruby 1.9.3dev (2011-09-23 revision 33323) [i686-linux]
Rails 3.0.20
Recently why working on a project on RSpecs related to DateTime on Rails I found out that
on a given date the values emitted by following statements
date.end_of_day.to_datetime
and
date.to_datetime.end_of_day
when compared returned false though they represented identical date-time.
To confirm this I opened up Rails console and tried out following
1.9.3dev :053 > monday = Time.now.monday
=> 2013-02-25 00:00:00 +0530
1.9.3dev :054 > monday.class
=> Time
1.9.3dev :055 > d1 = monday + 1.hour
=> 2013-02-25 01:00:00 +0530
1.9.3dev :056 > d2 = monday + 1.hour
=> 2013-02-25 01:00:00 +0530
1.9.3dev :058 > d1_eod_datetime = d1.end_of_day.to_datetime
=> Mon, 25 Feb 2013 23:59:59 +0530
1.9.3dev :059 > d2_eod_datetime = d2.to_datetime.end_of_day
=> Mon, 25 Feb 2013 23:59:59 +0530
1.9.3dev :061 > d1_eod_datetime == d2_eod_datetime
=> false
1.9.3dev :062 > d3_eod_datetime = d2.to_datetime.end_of_day
=> Mon, 25 Feb 2013 23:59:59 +0530
1.9.3dev :063 > d2_eod_datetime == d3_eod_datetime
=> true
and it seems my observation looks correct.That is:
When d1_eod_datetime and d2_eod_datetime are compared it returns false
When d2_eod_datetime and d3_eod_datetime are compared it returns true
It looks like an inconsistent behavior to me, however would appreciate if
anybody can make me understand what is going on behind the scenes and why the
comparisons made on values using date.end_of_day.to_datetime and
date.to_datetime.end_of_day fails though the source date object represents identical date-time.
Thanks,
Jignesh
Although their string representations are the same, d1_eod_datetime doesn't equal d2_eod_datetime. They differ in their least significant bits. If you convert your datetimes to a float representation, you can see that they're not equal:
d1_eod_datetime.to_f
=> 1381788000.0
d2_eod_datetime.to_f
=> 1381787999.0
The problem occurs when the Time instance receives the end_of_day message. Passing the end_of_day message to the Time instance returns a DateTime instance. The conversion to DateTime might result in a loss of accuracy and the new DateTime instance might not exactly equal to your original Time instance.
I have a page that is returning this as a date new Date(1357106400000) (which I believe is Javascript).
How do I convert that using Ruby. I've tried:
Date.new(1357106400000)
DateTime.new(1357106400000)
and many others, but I can't get the correct date to display.
The date returned should be 12/09/2012
I believe you've got the time in milliseconds since the epoch, and the function you're looking for is Time#at. But you need to down-convert into seconds before calling. For example:
[holt#Michaela ~]$ irb
irb(main):001:0> Time.at(1357106400000)
=> Wed Dec 28 00:00:00 +0000 44974
irb(main):002:0> Time.at(1357106400000 / 1000)
=> Wed Jan 02 06:00:00 +0000 2013
irb(main):003:0>
Not the exact day you thought it was, but probably still correct. Hope that helps!
In Javascript:
> new Date(1357106400000)
Wed Jan 02 2013 06:00:00 GMT+0000 (GMT Standard Time)
In Ruby:
> require 'date'
> DateTime.strptime("1357106400000", "%Q")
=> #<DateTime: 2013-01-02T06:00:00+00:00 ((2456295j,21600s,0n),+0s,2299161j)>
I want to be able to parse a Time from a string in Ruby (1.8.7), where the string does not contain any time zone information. I would like to treat the string as though it were in any of a number of time zones specified in this type of format: 'America/New_York'.
Time string example:
'2010-02-05 01:00:01'
I have spent quite a while trying to figure this one out.
I did find a similar question, but its answer does not apply in my case: How do I get Ruby to parse time as if it were in a different time zone?
The problem with the above solution is that my time zones cannot all be represented in the 3-letter format supported by Time.parse (http://www.ruby-doc.org/stdlib-1.8.7/libdoc/time/rdoc/classes/Time.html#M004931).
Is there a good way to accomplish what I'm trying to do here?
Edit: Made my answer actually appear as an answer.
require 'active_support/all'
time = ActiveSupport::TimeZone.new('UTC').parse('2010-02-05 01:00:01')
puts time
puts time.in_time_zone('EST')
Here's what I came up with using the tzinfo gem as suggested, though it seems rather complicated and unintuitive to me. As an end result I get the time parsed as though it were in the time zone I wanted, though represented by a Time object in UTC. I can also display it in the time zone I want using tzinfo's strftime:
jruby-1.6.1 :003 > time = '2010-05-01 01:00:00'
=> "2010-05-01 01:00:00"
jruby-1.6.1 :004 > tz = TZInfo::Timezone.get('America/New_York')
=> #<TZInfo::DataTimezone: America/New_York>
jruby-1.6.1 :005 > time += ' UTC'
=> "2010-05-01 01:00:00 UTC"
jruby-1.6.1 :006 > time = Time.parse(time)
=> Sat May 01 01:00:00 UTC 2010
jruby-1.6.1 :007 > time = tz.local_to_utc(time)
=> Sat May 01 05:00:00 UTC 2010
jruby-1.6.1 :010 > tz.strftime('%Y-%m-%d %H:%M:%S %Z', time)
=> "2010-05-01 01:00:00 EDT"
I believe this will suit my needs, but I wonder if I can get the Time to actually be in the timezone above (instead of just UTC).
You have two options the way I see it. On the one hand you could map the format you wish to use in an array (or any other structure you wish) to the 3-letter format used by Time.parse.
The other option is using the tzinfo gem as specified by my which seems to do the job quite nicely.
>> tz = TZInfo::Timezone.get("America/New_York")
=> #<TZInfo::DataTimezone: America/New_York>
>> tz.now
=> Thu Jul 07 16:29:13 UTC 2011
>> tz = TZInfo::Timezone.get("Europe/Rome")
=> #<TZInfo::DataTimezone: Europe/Rome>
>> tz.now
=> Thu Jul 07 22:30:03 UTC 2011