Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Ralph Johnson
Ralph Johnson
10,408 Points

how to return time on some other day than Jan 1 2000?

I have a form in Rails with a time_field entry. This provides a 3-column field, in the format hh:mm:AM/PM, with up and down arrows for each. So far so good. I can display that time on the show.html page and on the index.html page (for that model) as job.time.strftime("%I:%M%p"), which returns (e.g) a time such as "7:00am." All good. Nobody is the wiser.

But the actual database field reads 2000-01-01-0700 UTC, or 7am on Jan 1, 2000, in Greenwich, England.

First of all, I live in a place where jobs span two time zones (Mountain and Pacific), so I can't assume a start time is going to be in either one--I have to learn how to specify a time zone somehow. Secondly, I need to use time entries for reporting of hours worked (timesheets), so asking employees to do a mental conversion from Greenwich Mean Time, and also add 14 years to the Time, is a bit silly (and would cause chaos).

So I need to know how I can use a time_field to have the user enter a time, and then use code to convert it to reflect the actual time here in the US, and here in the second decade of the 21st century. And be entered in the database correctly. In Ruby I think I know how to do this (but without the database). In Rails, that's a horse of a different color--I'm not even sure which file the code would go in.

Any suggestions?

It goes in the controller, there you can use plain ruby to convert and pass the parameter back to that field after changing it

Ralph Johnson
Ralph Johnson
10,408 Points

based on Jason's ODOT tutorial (I revisited the code) it looks like this might be a ruby before_save action in the model.

So I used the following code:

before_save  :convert_start_time

def convert_start_time
      t = self.time
      d = self.start_date
      nt = Time.new(d.year, d.mon, d.day, t.hour, t.min, t.sec)
      self.time = nt
end

However, I've never discovered it if works because I'm having a problem with inconsistent errors cropping up when I use .strftime to format entries as they're being passed to the htm--SOMETIMES I get:

"undefined method `strftime' for nil:NilClass." 

And sometimes I DON'T, and everything works just fine. That's very confusing. Entering data in the form, then clicking submit, used to give me that error--and then the errors just stopped and it worked fine--I don't recall changing any code. Now the problem is cropping up on the index page, where it was working perfectly before.

On the index page for this model ("jobs"), and then on the the date value is displayed by using a variable (I've tried the markdown, and it isn't working right) without a "@", and on the show page the "@" is there, like an instance variable. I thought the problem, at first, was with the instance variable (and not the other form), but now it's cropping up in the place where it never did. I am perplexed, vexed, and stymied from proceeding until I can get these bugs worked out.

1 Answer

Brandon Barrette
Brandon Barrette
20,485 Points

You should have a time zone field in your users table so that a user can have a set time zone.

Then the datetime is stored in the database normally as the standard time (UTC time)

Then, when you go to display it, you can use ruby to convert the time from the database to the specific time zone for that user. (I would use a helper)

This way if a user changes times zones, its just a conversion of the UTC time in the database. You don't want to change the time and have inconsistent time/dates in the database. They all stay UTC and you convert them before displaying.

Ralph Johnson
Ralph Johnson
10,408 Points

Haven't tried datetime objects. I'll have to give that a shot and see what the various options are and what the various browser behaviors are in rails. Thanks for the tip.
The time, as it stands now, is being entered in UTC. Converting it kicks it forward 8 hours for display (and if I change it, in the database too). So thanks for that tip too. I'm not sure how (other than for display) the time zone figures in, given that. The worker would show up at 7 am at the work site, but the actual time would be 11 pm UTC. So I'm a bit perplexed on how to proceed here. Is there a way to adjust this at input?

Brandon Barrette
Brandon Barrette
20,485 Points

So the main thing is that you need to work with time zones and define them in your rails app. You should store all datetimes in your database as UTC to keep it consistent, then work to display it properly to the user.

I recommend that you use datetime and not date (as you will read in the reading below)

I'd read this:

http://www.elabs.se/blog/36-working-with-time-zones-in-ruby-on-rails

Ralph Johnson
Ralph Johnson
10,408 Points

I have run a migration to include a :timezone field in my database, and added this code to the html:

<%= f.label :timezone, "Time Zone" %>
<%= f.time_zone_select :timezone, ActiveSupport::TimeZone.us.zones, default: "Pacific Time (US & Canada)" %>

I created the new column as a string, because I was unable to find anything in any documentation indicating that there was another data type that would work. However, even though the dropdown menu works perfectly, the "show" page shows Timezone as blank, and when I check the database, even though I specified a default value, all my time zone entries are being stored as nil.

Am I doing something incorrectly here?

Brandon Barrette
Brandon Barrette
20,485 Points

Did you remember to include :time_zone in your permitted attributes in the controller?

Ralph Johnson
Ralph Johnson
10,408 Points

Nope! Thanks, Brandon, I'll go ahead and try that.