This question already has answers here:
Exponentiation in Ruby 1.8.7 Returns Wrong Answers
(5 answers)
Closed 9 years ago.
Here is what I have:
Using temporary variables, I have:
Why do 10 ** 18 and 10 ** 20 work fine, but 10 ** 19 doesn't?
It was a bug in Ruby 1.8.7. It has been fixed by this commit.
Just upgrade to the latest version and everything will work fine.
Here are some tests on 1.9.3:
Here is the text representation (for blind users):
1.9.3p362 :001 > 10 ** 18
=> 1000000000000000000
1.9.3p362 :002 > 10 ** 19
=> 10000000000000000000
1.9.3p362 :003 > 10 ** 20
=> 100000000000000000000
1.9.3p362 :004 > 10 ** 21
=> 1000000000000000000000
1.9.3p362 :005 > 10 ** 22
=> 10000000000000000000000
1.9.3p362 :006 > 10 ** 23
=> 100000000000000000000000
Here's the list of commands I've run:
irb
10 ** 18
10 ** 19
10 ** 20
10 ** 21
10 ** 22
10 ** 23
Related
Why won't Ruby's strptime convert this to a DateTime object:
DateTime.strptime('Monday 10:20:20', '%A %H:%M:%S')
# => ArgumentError: invalid date
While these work?
DateTime.strptime('Wednesday', '%A')
# => #<DateTime: 2015-11-18T00:00:00+00:00 ((2457345j,0s,0n),+0s,2299161j)>
DateTime.strptime('10:20:20', '%H:%M:%S')
# => #<DateTime: 2015-11-18T10:20:20+00:00 ((2457345j,37220s,0n),+0s,2299161j)>
This looks like a bug - minitech's comment is spot on. For now, though, a workaround (because you probably want this to work now):
You can split it on the space, get the date from the weekday, then get the time component from the other string (using the _strptime method minitech mentioned). Then you can set the time on the first date to the time component from the second string:
def datetime_from_weekday_time_string(string)
components = string.split(" ")
date = DateTime.strptime(components[0], '%A')
time = Date._strptime(components[1], '%H:%M:%S') # returns a hash like {:hour=>10, :min=>20, :sec=>20}
return date.change(time)
end
2.2.2 :021 > datetime_from_weekday_time_string("Monday 10:20:20")
=> Mon, 16 Nov 2015 10:20:20 +0000
2.2.2 :022 > datetime_from_weekday_time_string("Saturday 11:45:21")
=> Sat, 21 Nov 2015 11:45:21 +0000
2.2.2 :023 > datetime_from_weekday_time_string("Thursday 23:59:59")
=> Thu, 19 Nov 2015 23:59:59 +0000
I am using ruby 1.9.3 and want to get Date or Time object from 'mm/dd/yyyy' date format string
Time.zone.parse("12/22/2011")
this is giving me *** ArgumentError Exception: argument out of range
require 'date'
my_date = Date.strptime("12/22/2011", "%m/%d/%Y")
As above, use the strptime method, but note the differences below
Date.strptime("12/22/2011", "%m/%d/%Y") => Thu, 22 Dec 2011
DateTime.strptime("12/22/2011", "%m/%d/%Y") => Thu, 22 Dec 2011 00:00:00 +0000
Time.strptime("12/22/2011", "%m/%d/%Y") => 2011-12-22 00:00:00 +0000
(the +0000 is the timezone info, and I'm now in GMT - hence +0000. Last week, before the clocks went back, I was in BST +0100. My application.rb contains the line config.time_zone = 'London')
Try Time.strptime("12/22/2011", "%m/%d/%Y")
Would it be an option for you to use Time.strptime("01/28/2012", "%m/%d/%Y") in place of Time.parse? That way you have better control over how Ruby is going to parse the date.
If not there are gems: (e.g. ruby-american_date) to make the Ruby 1.9 Time.parse behave like Ruby 1.8.7, but only use it if it's absolutely necessary.
1.9.3-p0 :002 > Time.parse '01/28/2012'
ArgumentError: argument out of range
1.9.3-p0 :003 > require 'american_date'
1.9.3-p0 :004 > Time.parse '01/28/2012'
=> 2012-01-28 00:00:00 +0000
I am trying to write a CSV "fixer".
Unfortunately It seems that the csv.foreach instruction is not calling the lambda I have created. The CPU is used at 100%. Just wondering what ruby is doing in the meantime...
Any ideas why my code is wrong?
1 require "csv"
2
3 ARGV.empty? do
4 print "usage: fixcsv.rb <filename>"
5 exit
6 end
7
8 filename_orig = Dir.pwd + "/" + ARGV[0]
9 filename_dest = filename_orig.sub(/csv$/,"tmp.csv")
10 topic = filename_orig.sub(/_entries.csv$/,"").sub(/.*\//,"")
11
12 puts "topic:" + topic
13
14 writer = CSV.open(filename_dest,"w",:col_sep=>";")
15 #i=0
16 cycler = lambda do |row|
17 #i = i + 1
18 #puts "row number:" + i.to_str
19 #row[17] = topic
20 puts "foo"
21 writer << row
22 end
23
24 begin
25 CSV.foreach(filename_orig,:col_sep=>",",&cycler)
26 rescue
27 puts "exception:" + $!.message
28 exit
29 else
30 writer.close
31 end
Here is the stack trace produced when I Ctrl-C it:
stab#ubuntu:~/wok$ ruby addtopic.rb civilpoliticalrights_entries.csv
topic:civilpoliticalrights
^C/usr/lib/ruby/1.8/csv.rb:914:in `buf_size': Interrupt
from /usr/lib/ruby/1.8/csv.rb:825:in `[]'
from /usr/lib/ruby/1.8/csv.rb:354:in `parse_body'
from /usr/lib/ruby/1.8/csv.rb:227:in `parse_row'
from /usr/lib/ruby/1.8/csv.rb:637:in `get_row'
from /usr/lib/ruby/1.8/csv.rb:556:in `each'
from /usr/lib/ruby/1.8/csv.rb:531:in `parse'
from /usr/lib/ruby/1.8/csv.rb:311:in `open_reader'
from /usr/lib/ruby/1.8/csv.rb:94:in `foreach'
from addtopic.rb:25
EDIT: Ruby version is:
$ ruby --version
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
Your program worked fine for me in Ruby 1.9.
I have a few observations:
If your input pathname does not end in csv, then the input and output file names will be the same. This could easily produce an infinite loop.
You are definitely using the 1.9 flavor of csv. If this program needs to run on 1.8.7 it would need to have patches from the snippet below...
Mods for 1.8.7:
writer = CSV.open(filename_dest, "w", ?;)
#i=0
cycler = lambda do |row|
#i = i + 1
#puts "row number:" + i.to_str
#row[17] = topic
writer << row
end
begin
CSV.open filename_orig, 'r', ?,, &cycler
The main problem with 1.8.7 csv is that the interfaces to CSV.open and CSV.foreach do not take Hash options. Worse, they are expecting numeric code points, a feature of Ruby that apparently didn't work out and was withdrawn in 1.9.
I've been a bit spoiled by the joda-time API of:
DateTime now = new DateTime();
DateTime ninetyDaysAgo = now.minusDays(90);
I'm trying to do a similar thing in Ruby, but I'm
now = Time.now
ninetyDaysAgo = now - (90*24)
However, the math is off here (I'm really working with dates at midnight).
Is there friendly API for date subtraction?
require 'date'
now = Date.today
ninety_days_ago = (now - 90)
Running this thru the IRB console I get:
>>require 'date'
now = Date.today
ninety_days_ago = (now - 90)
require 'date'
=> false
now = Date.today
=> #<Date: 2011-03-02 (4911245/2,0,2299161)>
ninety_days_ago = (now - 90)
=> #<Date: 2010-12-02 (4911065/2,0,2299161)>
If you need the time you could just say now = DateTime.now
For those using Rails, check out the following:
DateTime.now - 10.days
=> Sat, 04 May 2013 12:12:07 +0300
20.days.ago - 10.days
=> Sun, 14 Apr 2013 09:12:13 UTC +00:00
If you're using Rails or don't mind including ActiveSupport, you can use the Numeric#days DSL like this:
ruby-1.9.2-p136 :002 > Date.today
=> Wed, 02 Mar 2011
ruby-1.9.2-p136 :003 > Date.today - 90.days
=> Thu, 02 Dec 2010
Since you are working with dates instead of times, you should also either start with Date instances, or convert your DateTime intances with #to_date. When adding/subtracting numbers from date instances, the numbers are implicitly days.
ruby-1.9.2-p136 :016 > DateTime.now.to_date
=> #<Date: 2011-03-02 (4911245/2,0,2299161)>
ruby-1.9.2-p136 :017 > DateTime.now.to_date - 90
=> #<Date: 2010-12-02 (4911065/2,0,2299161)>
Ruby supports date arithmetic in the Date and DateTime classes, which are part of Ruby's standard library. Both those classes expose #+ and #- methods, which add and subtract days from a date or a time.
$ irb
> require 'date'
=> true
> (DateTime.new(2015,4,1) - 90).to_s # Apr 1, 2015 - 90 days
=> "2015-01-01T00:00:00+00:00"
> (DateTime.new(2015,4,1) - 1).to_s # Apr 1, 2015 - 1 day
=> "2015-03-31T00:00:00+00:00"
Use the #<< and #>> methods to operate on months instead of days. Arithmetic on months is a little different than arithmetic on days. Using Date instead of DateTime makes the effect more obvious.
> (Date.new(2015, 5, 31) << 3).to_s # May 31 - 3 months; 92 days diff
=> "2015-02-28"
Following your joda-time example, you might write something like this in Ruby.
now = DateTime.now
ninety_days_ago = now - 90
or maybe just
ninety_days_ago = DateTime.now - 90
use the number of seconds:
Time.now - 90*24*60*60
This is a super old post, but if you wanted to keep with a Time object, like was originally asked, rather than switching to a Date object you might want to consider using Ruby Facets.
Ruby Facets is a standardized library of extensions for core Ruby classes.
http://rubyworks.github.io/facets/
By requiring Facets you can then do the following with Time objects.
Time.now.less(90, :days)
Simple solution using Rails Active Support:
days90_ago = 90.days.ago.to_date.to_s
OUTPUT:
puts 90_days_ago
=> "2019-10-09" # considering cur_date: 2020-01-07
I have "Date.today + 2.days" I need to format it using .strftime, but with the "+2.days" it doesn't recognize that method.Any ideas?
Those nice helpers don't come with a vanilla ruby install. You need the activesupport gem (part of Ruby on Rails).
$ gem install activesupport
$ irb
ruby-1.8.7-p249 > require 'rubygems'
=> true
ruby-1.8.7-p249 > require 'active_support'
=> true
ruby-1.8.7-p249 > Date.today
=> Fri, 16 Jul 2010
ruby-1.8.7-p249 > Date.today + 2.days
=> Sun, 18 Jul 2010
I don't see a problem, worked fine for me.
(Date.today + 2.days).strftime
#=> "2010-07-18"