TZ bug in Date and DateTime.strftime formatter?

Is this a bug?
I’m trying to get ruby to format a date, time or datetime to the proper
format for xmltv.
they key is in the timezone - I want it in +0100 format.

So look at this irb session.

First create some summer and winter dates in the form of Date, Time and
DateTime - they all have a time component but this always comes out
zeroed in Date.strftime as expected.

Im concentrating on the %z here because that’s what’s supposed to give
me the +0100 that I want.

Okay now lets create some summer and winter times:

irb(main):001:0> require ‘date’
=> true

Summer

irb(main):005:0> d_summer = Date.parse(“1 August 2006 15:25”)
=> #<Date: 4907897/2,0,2299161>

irb(main):006:0> t_summer = Time.parse(“1 August 2006 15:25”)
=> Tue Aug 01 15:25:00 GMT Daylight Time 2006

irb(main):007:0> dt_summer = DateTime.parse(“1 August 2006 15:25”)
=> #<DateTime: 706737353/288,0,2299161>

Winter

irb(main):008:0> d_winter = Date.parse(“1 November 2006 15:25”)
=> #<Date: 4908081/2,0,2299161>

irb(main):009:0> t_winter = Time.parse(“1 November 2006 15:25”)
=> Wed Nov 01 15:25:00 GMT Standard Time 2006

irb(main):010:0> dt_winter = DateTime.parse(“1 November 2006 15:25”)
=> #<DateTime: 706763849/288,0,2299161>

Now format the times

irb(main):011:0> d_winter.strftime(’%z’)
=> “+0000”
irb(main):012:0> d_summer.strftime(’%z’)
=> “+0000”
irb(main):013:0> t_winter.strftime(’%z’)
=> “GMT Standard Time”
irb(main):014:0> t_summer.strftime(’%z’)
=> “GMT Daylight Time”
irb(main):015:0> dt_winter.strftime(’%z’)
=> “+0000”
irb(main):016:0> dt_summer.strftime(’%z’)
=> “+0000”

See what’s happening: Time always gives the full string for the
timezone, and it correctly varies it for summer versus winter: “GMT
Standard Time” vs “GMT Daylight Time”

Now Date, and DateTime give me the numeric format I wanted. The winter
format is correct for me - I’m on GMT in winter, but look at the Summer
format: it’s the same as for Winter

It seems to me that if Time.strftime makes the difference, then Date and
DateTime should too.
I expected to see +0100 for the summer times. And so does my Media
Center for that matter, so this will cause my EPG to be off by an hour
unless I correct it myself.

Anyone else noticed this?

I understand the system strftime is used by ruby, so I guess it might be
in Windows (I’m using XP). I haven’t programmed in C on this windows
box, but I have in C#, and there I get the correct result from
dateTime.ToString(“yyyyMMddHHmmss zzzz”), which no-doubt is using some
.Net framework version of the time routine, not the same one as ruby.

Anyway, this is a bug right?
Is it specific to windows (XP, SP2 is what I’m using)

If it is a bug is it fixed or fixable?
Is there an easy way to correct - it? A different Time support class?
(I was thinking of just parsing the output from Time.strftime for the
“Daylight” and creating my own string.

(I’m in Portugal by the way, and writing this during daylight savings at
the end of March, so my current tz is GMT Daylight Time - same as the
UK)

On 3/31/07, rhubarb [email protected] wrote:

irb(main):016:0> dt_summer.strftime(‘%z’)

box, but I have in C#, and there I get the correct result from

(I’m in Portugal by the way, and writing this during daylight savings at
the end of March, so my current tz is GMT Daylight Time - same as the
UK)

I get the same results in my Fedora Core 6 system (ruby-1.8.5.35),
except that I don’t seem to have Time.parse.

Haven’t played much with dates and Ruby, but from date.rb’s rdoc
(http://www.ruby-doc.org/stdlib/libdoc/date/rdoc/files/date_rb.html):
“DateTime objects support a simple representation of time zones. …
This simple representation of time zones does not take into account
the common practice of Daylight Savings Time or Summer Time.”

And also: “The Date class does not support time zone offsets, in
that there is no way to create a Date object with a time zone.”

rhubarb wrote:

Is this a bug?
I’m trying to get ruby to format a date, time or datetime to the proper
format for xmltv.
they key is in the timezone - I want it in +0100 format.

Would this do the trick:
http://rubyforge.org/projects/tzinfo/


Phillip “CynicalRyan” Gawlowski
http://cynicalryan.110mb.com/

Eek! That was supposed to be My Special Law, MY special law, I tell
you!

T/

Would this do the trick:
http://rubyforge.org/projects/tzinfo/

This is a handy little library, but it doesn’t have a way of getting the
current timezone for the location where it’s run.
Time does this.

And also: “The Date class does not support time zone offsets, in
that there is no way to create a Date object with a time zone.”

This seems to be the key. It’s just not supported. That makes no sense
really. With support in Time, and the ability to format a DateTime to
show the timezone, there’s no excuse for Ruby not givign the correct
value of +0100.

With all those libraries out there I’m surprised something this basic
isn’t available.

I guess I’ll just parse for the Daylight part and make my own offset -
but it’s a shame since my xml-tv code would otherwise be general - now
it’s going to be specific to my timezone

The plot thickens.

Playing around with DateTime I thought I had it. DateTime.now.zone seems
to give the right result. So I went back to my test cases. Look at this:

irb(main):008:0> dt_summer = DateTime.parse(“1 August 2006 15:25”)
=> #<DateTime: 706737353/288,0,2299161>
irb(main):009:0> dt_winter = DateTime.parse(“1 November 2006 15:25”)
=> #<DateTime: 706763849/288,0,2299161>
irb(main):010:0> dt_summer.zone
=> “Z”
irb(main):011:0> dt_winter.zone
=> “Z”
irb(main):012:0> dt = DateTime.now
=> #<DateTime: 212042973457327/86400000,1/24,2299161>
irb(main):013:0> dt.zone
=> “+0100”

So the zone for a parsed DateTime is ‘Z’ but for ‘now’ is correct at
‘+0100’

!#$%#$@ (As they used to say in the comic books, not realizing that
they were coding in perl)

Possible solution?

I still have no idea why a parsed Time and Time.now seem to be different
types of object - though .class returns the same class Time.
So I still don’t understand why Time.now.zone gives me the zone in one
form and the parsed time gives it in another.

I’m still working on my own solution and this is what I’ve come up with.
First a bit more experimenting:

irb(main):042:0> t_summer = Time.parse(“1 July 2006 15:25”)
=> Sat Jul 01 15:25:00 GMT Daylight Time 2006

irb(main):051:0> t_summer.public_methods
=> [“instance_variable_get”, “succ”, “year”, “to_f”, “to_s”, “getutc”,
“respond_to?”, “clone”, “utc”, “nil?”, “require_gem_with_options”,
“instance_variable_set”, “wday”, “send”, “inspect”, “asctime”,
“utc?”, “to_yaml_style”, “_dump”, “dup”, “equal?”, “ctime”, “yday”,
“methods”, “gmt?”, “pretty_print_cycle”, “send”, “sec”, “taguri”,
“taint”, “tv_sec”, “eql?”, “taguri=”, “display”, “hash”, “isdst”,
“singleton_methods”, “pretty_print”, “instance_eval”, “hour”, “to_yaml”,
“instance_of?”, “tv_usec”, “pretty_print_instance_variables”, “rfc2822”,
“id”, “protected_methods”, “mday”, “tainted?”, “to_yaml_properties”,
“kind_of?”, “untaint”, “usec”, “localtime”, “dst?”, “rfc822”, “id”,
“zone”, “+”, “private_methods”, “day”, “-”, “freeze”, “extend”,
“strftime”, “is_a?”, “gmtime”, “min”, “object_id”, “gmtoff”, “httpdate”,
“require_gem”, “<=>”, “==”, “public_methods”, “mon”, “===”, “between?”,
“>=”, “<=”, “getlocal”, “gmt_offset”, “pretty_print_inspect”,
“xmlschema”, “type”, “=~”, “instance_variables”, “<”, “require”,
“frozen?”, “month”, “method”, “>”, “to_i”, “to_a”, “getgm”, “iso8601”,
“class”, “utc_offset”]

irb(main):052:0> t_summer.httpdate
=> “Sat, 01 Jul 2006 14:25:00 GMT”

irb(main):053:0> t_summer.rfc822
=> “Sat, 01 Jul 2006 15:25:00 +0100”

irb(main):054:0> t_summer.rfc2822
=> “Sat, 01 Jul 2006 15:25:00 +0100”

irb(main):055:0> t_summer.xmlschema
=> “2006-07-01T15:25:00+01:00”

irb(main):056:0> t_summer.iso8601
=> “2006-07-01T15:25:00+01:00”

irb(main):057:0> t_summer.utc_offset
=> 3600
irb(main):058:0> t_summer.gmt_offset
=> 3600

irb(main):059:0> t_summer.zone
=> “GMT Daylight Time”

So the most likely candidates are:

  1. Parse the output of Time.xmlschema or Time.iso8601 (identical?) from
    the last + or - to the end and get rid of the colon (I want 0100, not
    01:00)

  2. Do the same but use rfc822 or rfc2822 (why do both exist, for
    goodness sake - they seem identical?). Actually this makes more sense,
    since there’s a space before the + and no :. In fact I could just take
    the last 5 chars.

  3. Use gmt_offset or utc_offset (identical?) and convert from seconds to
    hours

I’m going with 2, it looks the surest and simplest.

Here it is in action:

irb(main):063:0> t_summer.rfc822[-5…-1]
=> “+0100”

irb(main):065:0> t_winter.rfc822[-5…-1]
=> “+0000”

That’ll have to do me. Anyone else have any ideas?