TZ bug in Date and DateTime.strftime formatter?

R

rhubarb

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)
 
F

Felipe Contreras

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)

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.
 
L

Luis Parravicini

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."
 
R

Rover Rhubarb

Would this do the trick:

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
 
R

Rover Rhubarb

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)
 
R

Rover Rhubarb

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?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,821
Messages
2,569,747
Members
45,726
Latest member
RaleighAll

Latest Threads

Top