Issue With .next_month in Ruby - ruby

In my local enviroment everything works fine. When I upload to my server, I keep getting an Internal Server Error. I've commented out my code until I found the offending line which is:
dateObj = dateObj.next_month #Problem Child
Here is the complete code:
def makeCal(dateObj)
cal = Hash.new
months = 0
while months < 12
# #pass dateobj to build array
array = buildArray(dateObj)
# #save array to hash with month key
monthName = Date::MONTHNAMES[dateObj.mon]
cal[monthName] = array
# #create new date object using month and set it to the first
date = dateObj.month.to_s + '/' + 1.to_s + '/' + dateObj.year.to_s
dateObj = Date.strptime(date, "%m/%d/%Y")
puts dateObj.kind_of? Date
dateObj = dateObj.next_month #Problem Child
months = months + 1
end
cal
end
And ruby -v locally:
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0]
and ruby -v remotely:
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]
Any ideas on how to solve this?
UPDATE:
173.26.190.206 - - [03/Sep/2011 10:40:17] "POST /calendar " 500 30 0.0020
That's from nginx
and this is the stack trace:
NoMethodError - undefined method `next_month' for #<Date: 4911549/2,0,2299161>:
./main.rb:82:in `makeCal'
./main.rb:120:in `POST /calendar'
I inserted the line: puts dateObj.kind_of? Date
and I get all true. So my dateObj is of kind Date

It seems that you lack
require 'active_support'
BTW, if all you need from it is next_month, you can use
date_obj >>= 1
as Date#>> is part of core library.
Edit:
For getting the first of the month, you can use:
Date.new(date_obj.year, date_obj.month)

Related

Measuring against a future time in Ruby

I'd like to be able to run a method which will measure Time.now against a future date, something like this:
def graduated?
Time.now == # future date ? (puts "Congrats!") : (puts "Not there yet!")
end
I've tried entering the syntax from ruby docs for the future date as such: 2015-8-7
but that is not correct. Could someone correct my syntax on how to hard code a future date to compare against?
If you just enter "2015-8-7" that's a string, you'll want a Time object. This should point you in the right direction:
2.2.0 :001 > other = Time.new(2015, 8, 7)
=> 2015-08-07 00:00:00 -0500
2.2.0 :002 > Time.now < other
=> true
2.2.0 :003 > Time.now > other
=> false
You can also use the Date object, and Date.today, Date.new(2015, 8, 7) and get similar results.

invalid date using Ruby 1.9.2

Why is 'time' being returned as an invalid date?
val = "9/22/2011 4:23 AM"
time = DateTime.parse(val).strftime("%Y-%m-%d %H:%M:%S").to_datetime
#at breakpoint: time = 2011-09-22T04:23:00+00:00 as a DateTime Object
#form_entry.storage_datetime = time # crashes here with invalid date
If it helps, I'm using gem mysql 2.8.1 and Ruby 1.9.2. Thanks
I got an ArgumentError on line two; couldn't create the DateTime object in the first place.
Try using strptime instead:
val = "9/22/2011 4:23 AM"
DateTime.strptime(val, "%m/%d/%Y %H:%M %p")
=> #<DateTime: 2011-09-22T04:23:00+00:00 (3536390423/1440,0/1,2299161)>

How do I add two weeks to Time.now?

How can I add two weeks to the current Time.now in Ruby? I have a small Sinatra project that uses DataMapper and before saving, I have a field populated with the current time PLUS two weeks, but is not working as needed. Any help is greatly appreciated! I get the following error:
NoMethodError at /
undefined method `weeks' for 2:Fixnum
Here is the code for the Model:
class Job
include DataMapper::Resource
property :id, Serial
property :position, String
property :location, String
property :email, String
property :phone, String
property :description, Text
property :expires_on, Date
property :status, Boolean
property :created_on, DateTime
property :updated_at, DateTime
before :save do
t = Time.now
self.expires_on = t + 2.week
self.status = '0'
end
end
You don't have such nice helpers in plain Ruby. You can add seconds:
Time.now + (2*7*24*60*60)
But, fortunately, there are many date helper libraries out there (or build your own ;) )
Ruby Date class has methods to add days and months in addition to seconds in Time.
An example:
require 'date'
t = DateTime.now
puts t # => 2011-05-06T11:42:26+03:00
# Add 14 days
puts t + 14 # => 2011-05-20T11:42:26+03:00
# Add 2 months
puts t >> 2 # => 2011-07-06T11:42:26+03:00
# And if needed, make Time object out of it
(t + 14).to_time # => 2011-05-20 11:42:26 +0300
require 'rubygems'
require 'active_support/core_ext/numeric/time'
self.expires = 2.weeks.from_now
You have to use seconds to do calculation between dates, but you can use the Time class as a helper to get the seconds from the date part elements.
Time.now + 2.week.to_i
EDIT: As mentioned by #iain you will need Active Support to accomplish usign 2.week.to_i, if you can't (or don't want to) have this dependency you can always use the + operator to add seconds to a Time instance (time + numeric → time docs here)
Time.now + (60 * 60 * 24 * 7 * 2)
I think week/weeks is defined in the active support numeric extension
$ ruby -e 'p Time.now'
2011-05-05 22:27:04 -0400
$ ruby -r active_support/core_ext/numeric -e 'p Time.now + 2.weeks'
2011-05-19 22:27:07 -0400
You can use these 3 patterns
# you have NoMethod Error undefined method
require 'active_support/all'
# Tue, 28 Nov 2017 11:46:37 +0900
Time.now + 2.weeks
# Tue, 28 Nov 2017 11:46:37 +0900
Time.now + 2.week
# Tue Nov 28 11:48:24 +0900 2017
2.weeks.from_now
<%current_time=Time.now
current_time_s=current_time.strftime('%Y-%m-%d %H:%M:%S').to_s #show currrent date time
current_time= Time.now + (60 * 60 * 24 * 7 * 250)
current_time_e=current_time.strftime('%Y-%m-%d %H:%M:%S').to_s #show datetime after week
%>
I like mine too :)
def minor?(dob)
n = DateTime.now
a = DateTime.parse(dob)
a >> 12*18 > n
end
Saves you the trouble of thinking about leap years and seconds. Just works out of the box.

csv.foreach stuck, not calling the block

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.

get next/previous month from a Time object

I have a Time object and would like to find the next/previous month. Adding subtracting days does not work as the days per month vary.
time = Time.parse('21-12-2008 10:51 UTC')
next_month = time + 31 * 24 * 60 * 60
Incrementing the month also falls down as one would have to take care of the rolling
time = Time.parse('21-12-2008 10:51 UTC')
next_month = Time.utc(time.year, time.month+1)
time = Time.parse('01-12-2008 10:51 UTC')
previous_month = Time.utc(time.year, time.month-1)
The only thing I found working was
time = Time.parse('21-12-2008 10:51 UTC')
d = Date.new(time.year, time.month, time.day)
d >>= 1
next_month = Time.utc(d.year, d.month, d.day, time.hour, time.min, time.sec, time.usec)
Is there a more elegant way of doing this that I am not seeing?
How would you do it?
Ruby on Rails
Note: This only works in Rails (Thanks Steve!) but I'm keeping it here in case others are using Rails and wish to use these more intuitive methods.
Super simple - thank you Ruby on Rails!
Time.now + 1.month
Time.now - 1.month
Or, another option if it's in relation to the current time (Rails 3+ only).
1.month.from_now
1.month.ago
Personally I prefer using:
Time.now.beginning_of_month - 1.day # previous month
Time.now.end_of_month + 1.day # next month
It always works and is independent from the number of days in a month.
Find more info in this API doc
you can use standard class DateTime
require 'date'
dt = Time.new().to_datetime
=> #<DateTime: 2010-04-23T22:31:39+03:00 (424277622199937/172800000,1/8,2299161)>
dt2 = dt >> 1
=> #<DateTime: 2010-05-23T22:31:39+03:00 (424282806199937/172800000,1/8,2299161)>
t = dt2.to_time
=> 2010-05-23 22:31:39 +0200
There are no built-in methods on Time to do what you want in Ruby. I suggest you write methods to do this work in a module and extend the Time class to make their use simple in the rest of your code.
You can use DateTime, but the methods (<< and >>) are not named in a way that makes their purpose obvious to someone that hasn't used them before.
If you do not want to load and rely on additional libraries you can use something like:
module MonthRotator
def current_month
self.month
end
def month_away
new_month, new_year = current_month == 12 ? [1, year+1] : [(current_month + 1), year]
Time.local(new_year, new_month, day, hour, sec)
end
def month_ago
new_month, new_year = current_month == 1 ? [12, year-1] : [(current_month - 1), year]
Time.local(new_year, new_month, day, hour, sec)
end
end
class Time
include MonthRotator
end
require 'minitest/autorun'
class MonthRotatorTest < MiniTest::Unit::TestCase
describe "A month rotator Time extension" do
it 'should return a next month' do
next_month_date = Time.local(2010, 12).month_away
assert_equal next_month_date.month, 1
assert_equal next_month_date.year, 2011
end
it 'should return previous month' do
previous_month_date = Time.local(2011, 1).month_ago
assert_equal previous_month_date.month, 12
assert_equal previous_month_date.year, 2010
end
end
end
below it works
previous month:
Time.now.months_since(-1)
next month:
Time.now.months_since(1)
I just want to add my plain ruby solution for completeness
replace the format in strftime to desired output
DateTime.now.prev_month.strftime("%Y-%m-%d")
DateTime.now.next_month.strftime("%Y-%m-%d")
You can get the previous month info by this code
require 'time'
time = Time.parse('2021-09-29 12:31 UTC')
time.prev_month.strftime("%b %Y")
You can try convert to datetime.
Time gives you current date, and DateTime allows you to operate with.
Look at this:
irb(main):041:0> Time.new.strftime("%d/%m/%Y")
=> "21/05/2015"
irb(main):040:0> Time.new.to_datetime.prev_month.strftime("%d/%m/%Y")
=> "21/04/2015"
Here is a solution on plain ruby without RoR, works on old ruby versions.
t=Time.local(2000,"jan",1,20,15,1,0);
curmon=t.mon;
prevmon=(Time.local(t.year,t.mon,1,0,0,0,0)-1).mon ;
puts "#{curmon} #{prevmon}"
Some of the solutions assume rails. But, in pure ruby you can do the following
require 'date'
d = Date.now
last_month = d<<1
last_month.strftime("%Y-%m-%d")
Im using the ActiveSupport::TimeZone for this example, but just in case you are using Rails or ActiveSupport it might come in handy.
If you want the previous month you can substract 1 month
time = Time.zone.parse('21-12-2008 10:51 UTC')
time.ago(1.month)
$ irb
irb(main):001:0> time = Time.now
=> 2016-11-21 10:16:31 -0800
irb(main):002:0> year = time.year
=> 2016
irb(main):003:0> month = time.month
=> 11
irb(main):004:0> last_month = month - 1
=> 10
irb(main):005:0> puts time
2016-11-21 10:16:31 -0800
=> nil
irb(main):006:0> puts year
2016
=> nil
irb(main):007:0> puts month
11
=> nil
irb(main):008:0> puts last_month
10
=> nil

Resources