dodgerogers747
dodgerogers747

Reputation: 3345

How do I use the Time class on hash values?

I am working through Chris Pine's Ruby book, and I am slightly confused why my code doesn't quite work.

I have a file called birthdays.txt which has around 10 lines of text which resembles:

Andy Rogers, 1987, 02, 03

etc.

My code as follows:

hash = {}

File.open('birthdays.txt', "r+").each_line do |line|
  name, date = line.chomp.split( /, */, 2 )
  hash[name] = date
end

puts 'whose birthday would you like to know?'

name = gets.chomp
puts hash[name]                                    
puts Time.local(hash[name])

My question is, why does the last line of code, Time.local(hash[name]) produce this output?:

1987-01-01 00:00:00 +0000 

instead of:

1987-02-03 00:00:00 +0000

Upvotes: 0

Views: 85

Answers (3)

dodgerogers747
dodgerogers747

Reputation: 3345

hash = {}


File.open('birthdays.txt').each_line do |line|
  line = line.chomp
  name, date = line.split(',',2)
  year, month, day = date.split(/, */).map {|x| x.to_i}
  hash[name] = Time.local(year, month, day)
end

puts 'Whose birthday and age do you want to find out?'
name = gets.chomp

    if hash[name] == nil
       puts ' Ummmmmmmm, dont know that one'
    else
       age_secs = Time.new - hash[name]
       age_in_years = (age_secs/60/60/24/365 + 1)

  t = hash[name]
  t.strftime("%m/%d/%y")
  puts "#{name}, will be, #{age_in_years.to_i} on #{t.strftime("%m/%d/")}"
end

had to move the Time.local call earlier in the program and then bingo, cheers guys!

Upvotes: 0

steenslag
steenslag

Reputation: 80085

line = "Andy Rogers, 1987, 02, 03\n"
name, date = line.chomp.split( /, */, 2 ) #split (', ', 2) is less complex.
#(Skipping the hash stuff; it's fine)
p date #=>          "1987, 02, 03"
# Time class can't handle one string, it wants: "1987", "02", "03"
# so: 
year, month, day = date.split(', ')
p Time.local(year, month, day)
# or do it all at once (google "ruby splat operator"):
p Time.local(*date.split(', '))

Upvotes: 0

YenTheFirst
YenTheFirst

Reputation: 2192

If you look at the documentation for Time.local,

Time.local doesn't parse a string. It expects you to pass a separate parameter for year, month, and date. When you pass a string like "1987, 02, 03", it takes that to be a single parameter, the year. It then tries to coerce that string into an integer - in this case, 1982.

so, basically, you want to slice up that string into the year, month, and day. there's multiple ways to do this. Here's one (it can be made shorter, but this is the most clear way)

year, month, date = date.split(/, */).map {|x| x.to_i}
Time.local(year, month, date)

Upvotes: 2

Related Questions