Time Converstions Issues

The Time object in Rails 2.3.2 is problematic because it acts like a datetime whenever possible, especially in hash conversions.

I am not using time zones, and I am not using and Datetimes. The mysql Time object simply holds a string, hh:mm:ss. All I want to do is render :xml with that time to show up that way, no UTC and no date, just hh:mm:ss

I can override time.to_s in enviornment.rb but when I use the to_xml it still defaults to the datetime format. I tried to override the attribute reader and then I get this error.

NoMethodError: undefined method `xmlschema' for "21:25:42":String from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/ active_support/core_ext/hash/conversions.rb:38

After looking into conversions.rb. It appears that rails thinks of time as a datetime and this doesn't seem proper, especially when Date does not. Why should a random date be assigned to the time?

I'll happily make a patch, but I thought to ask if there was some sort of reasoning behind this, or a special circumstance I will destroy when allowing to a Time hash conversion like Date has, which is independent of datetime?

-Josh

After looking into conversions.rb. It appears that rails thinks of time as a datetime and this doesn't seem proper, especially when Date does not. Why should a random date be assigned to the time?

I'll happily make a patch, but I thought to ask if there was some sort of reasoning behind this, or a special circumstance I will destroy when allowing to a Time hash conversion like Date has, which is independent of datetime?

The root of the issue is that there is no pure time of day class in ruby (which is why Time is used). Maybe the right thing to do would be to write such a class (although you'd have a large backwards compatibility task).

Fred

Right.

Ruby Time and DateTime instances both represent a point in time (which includes the date). They vary mostly in internal representation. DateTIme has a broader range that it can represent, since TIme uses the underlying C library time data structures and has a platform dependent earliest and latest value.

ActiveSupport has a Duration class, which is closer to something like the time interval which the OP seems to be seeking. But Duration is really used only to represent a value to be added/subtracted from a Time/Date time. It's what you get when you evaluate an expression like 1.second, 1.hour, or (1.second + 1.hour). And it normally comes into play in an expressions like

Time.now + 1.day

or 1.week.from_now

You said that you have a time object but that it holds a "string". If you are updating your mysql db with a string format of time and you specify the column as a string you can return it as a string and format it anyway you want using gsub.

In either case, you can convert anything returned from mysql using gsub.

The first question you should ask yourself is what type of column do I have in my mysql db?

Thanks for all the points and it is useful to think about the rails time not having time_of_day. I still am not sure my problem was clear. It seems to me that there should at least be a :emulate_datetime => false sort of option like with booleans, ex.

ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false

The table simply holds 21:25:42, but activerecord retrieves the information in the AR Hash as

time => "2000-01-01 21:25:42"

Where then does date, 2000-01-01 come from? It looks to me like rails is just guessing, Shouldn't thee be a way for it to retreive time as a string, time=> "2001-01-01" ?

I think the last suggestion from Alpha Blue will have to be my current solution, don't use the mysql time object and instead use a string.

If you use a string in the db to hold time then you will not be able to do a find querying for all records where the time is within a range, for example, though this may not be an issue. Unless you use LIKE on the string which could get messy. If you just remember to always ignore the date part of the DateTime object then all will be well.

Somebody should develop a TimeOfDay class derived from DateTime that handles any messiness automatically. It is on my list but I have not managed to get round to it so far.

Colin

You may be interested in the _before_type_cast accessor - that will let you read whatever the DB is actually returning.

I'm somewhat curious what makes sense for a dateless, zoneless time. Either the app that consumes the data is *assuming* the missing info (hard to do, as even time comparisons get nasty across DST boundaries) or the data is (maybe?) some kind of elapsed time.

--Matt Jones

What time do you normally wake up? 7:00 would be one answer :slight_smile: No date or TZ associated with that...

Hassan Schroeder wrote:

I'm somewhat curious what makes sense for a dateless, zoneless time.

What time do you normally wake up? 7:00 would be one answer :slight_smile: No date or TZ associated with that...

I don't really think I agree. When I go to sleep tonight, I will get up at 7:30 a.m. Eastern Time (not Pacific or Central European), on Tuesday 14 July 2009 (not Wednesday 15 July).

-- Hassan Schroeder

Best,

"what time will you get up tomorrow" and "what time do you typically get up" seem pretty obviously different to me... :slight_smile:

Hassan Schroeder wrote: [...]

"what time will you get up tomorrow" and "what time do you typically get up" seem pretty obviously different to me... :slight_smile:

True. But even here, there's a time zone. If I get up at 7:30 Pacific Time tomorrow instead of 7:30 Eastern Time, I will miss my appointments. If I get up at 7:30 Central European Time, I'll be extremely tired from getting only about 3 hours of sleep. A time without a time zone is 100% meaningless.

-- Hassan Schroeder

Best,

And that's 100% silly. If I say that I typically get up at 7:00, it's totally irrelevant where I am. I get up at 7 in San Jose. I get up at 7 in New York. I get up at 7 in Frankfurt. I get up at 7 in Ubud. It's 7 hours after midnight wherever I happen to be.

There is utterly no "time zone" component to the concept (and use case) I'm talking about.

Hassan Schroeder wrote: [...]

And that's 100% silly. If I say that I typically get up at 7:00, it's totally irrelevant where I am. I get up at 7 in San Jose. I get up at 7 in New York. I get up at 7 in Frankfurt. I get up at 7 in Ubud. It's 7 hours after midnight wherever I happen to be.

Yes -- *wherever you happen to be*. Not in some other time zone.

There is utterly no "time zone" component to the concept (and use case) I'm talking about.

There absolutely is a time zone component -- namely, the local time zone. This would be like saying (in Rubyish pseudocode:

@hassan.set_alarm(Time.new(:hour => 7, :minute => 0, :zone => DEFAULT_TIME_ZONE)) # I know Time.new's syntax is not like this -- just trying for clarity.

A clock time cannot be a useful without a time zone -- even if that time zone is set to a sensible default, it's still *there*.

Best,

Gah. I give up. That's like saying you can't discuss the abstract idea of "pancakes" without specifying the meal they will be (or were) eaten at.

Sorry you can't visualize the use case of an *abstract* time of day.

But whatever.

It might, but it isn't to me, and it *isn't the use case I described*.

"What time do you typically get up?" How simple is that?

Build me a survey form, collect the responses, calculate average, mean, do whatever desired statistical analysis, on data in the range of 00:00 to 23:59.

But there is not *any* time zone info associated with that. Period. It simply isn't part of the question. Utterly, totally, irrelevant.

Hassan Schroeder wrote:

I do understand that it might be useful to do

@hassan.set_alarm_clock(AbstractTime.new(:hour => 7, :minute => 0))

It might, but it isn't to me, and it *isn't the use case I described*.

"What time do you typically get up?" How simple is that?

Build me a survey form, collect the responses, calculate average, mean, do whatever desired statistical analysis, on data in the range of 00:00 to 23:59.

Yes, that would be a perfect candidate for AbstractTime...now I understand your use case! (Though to me, at least, it's nearly equivalent to the use case I described with the alarm.)

But there is not *any* time zone info associated with that. Period. It simply isn't part of the question. Utterly, totally, irrelevant.

In this use case, you are quite right about that. Thanks for the explanation.

-- Hassan Schroeder ------------------------ hassan.schroeder@gmail.com twitter: @hassan

Best,

Many use cases for a TimeOfDay do imply or require a time zone, some uses cases do not, but there are certainly many use cases for TimeOfDay where the Date is irrelevant. It is the fact that a db Time object maps to a DateTime in Rails and then we have to mess about explicitly ignoring the Date part that is the key annoyance for me.

Colin

But there are definitely use cases where the time zone is NOT inherently part of the time value.

I've spent quite a bit of time looking at things like this in implementing ri_cal. One set of use cases comes from the various ways RFC 2445 allows date/date-time values to be represented in icalendar data.

It may be expressed in UTC or Zulu time. For example within an event might have its start time specified by:    DTSTART:200907T1100000Z

It may be expressed with a specific local time zone e.g.    DTSTART;TZID=America/New_York:200907T14070000

It may be expressed with a floating time zone   DTSTART:20090714T070000

In this last case the actual time is determined by having the time zone supplied by the user or the user's calendar application, presumably that will be the user's local time zone.

Uses for floating times might be to represent when the beginning of the New Year is celebrated, which tends to happen at xxxx0101T000000

or midnight at the beginning of 1 January in each local time zone.

Or expressing that I wake up, or try to, at 7:00 a.m. in whatever time zone I happen to find my body in.

The last RFC value for a time attribute is just a date e.g. DTSTART:20090714 which is inherently floating with respect to time zone.

That said, this discussion has been ignoring the fact that a time might not represent a time of day, but can in certain cases represent a duration, and there are differing standards on representing these.

RFC2445 has a period value which represents a signed time duration, which can have week, day, hour, minute and second parts.

The Duration class in ActiveSupport is similar, it represents a signed period with the same parts as are defined for Time#advance, years, months, days, hours, minutes, and seconds. But as far as I can tell, this really isn't surfaced very well, in rails durations are pretty much used as temporary results in time calculations.

And some SQL implementations, MySQL for one, have time values which are really durations with hour, minute, and second parts. MySql allows such a time to represent periods longer than a day, so 132:20:00 is a valid time, although it would be a lousy time of day, except perhaps for Bill Murray's character in Ground Hog Day to use.

I asked a similar question on #jruby yesterday and got the answer that all times have a date/TZ component.

I'm developing a running log and need *only* hh:mm:ss (no TZ or date component) to store the time taken to run a particular distance. AIU, there is no clean solution and so using datetime and then masking date.

Is there something better ?

-Arun