marcusaram / snakeyaml

Automatically exported from code.google.com/p/snakeyaml
Apache License 2.0
1 stars 0 forks source link

GregorianCalendar should be output as regular Timestamp #49

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
GregorianCalendar recurses as a bean instead, and fails on load trying to build 
a timezone.

i.e.:

!!java.util.GregorianCalendar
  firstDayOfWeek: 1
  gregorianChange: 1582-10-15T00:00:00Z
  lenient: true
  minimalDaysInFirstWeek: 1
  time: 2009-11-06T00:10:04.373Z
  timeInMillis: 1257466204373

Since Gregorian Calendar is one of the official approved ways to store a 
date/time, this should 
work as any other Yaml date/time

Probably best to turn it into an ISO string instead. 

Original issue reported on code.google.com by obast...@gmail.com on 11 Feb 2010 at 10:03

GoogleCodeExporter commented 9 years ago
GregorianCalendar is not a timestamp.
JavaDoc:
GregorianCalendar is a concrete subclass of Calendar  and provides the standard 
calendar used by most of the world.
As of JDK 1.1, the Calendar class should be used to convert between dates and 
time 
fields.

Use java.util.Date instead to represent date/time.

Original comment by py4fun@gmail.com on 12 Feb 2010 at 9:06

GoogleCodeExporter commented 9 years ago
It's not that simple.

The world is round. 

GregorianCalendar is the only java Time/Date class that actually has a 
timeZone. Therefore its the only way to 
represent date/time here on planet earth. 

If you want to read in this time:

iso8601: 2001-12-14t21:59:43.10-05:00

The only way to correctly store that without losing information in Java is as a 
GregorianCalendar. 
java.util.Date is defined to be in UTC, so either you have to add 5:00 to the 
above, or drop it entirely. 

Original comment by obast...@gmail.com on 12 Feb 2010 at 3:19

GoogleCodeExporter commented 9 years ago
>If you want to read in this time:
>iso8601: 2001-12-14t21:59:43.10-05:00
>The only way to correctly store that without losing information in Java is as 
a 
>GregorianCalendar. 

This is not true !
Please do not use GregorianCalendar where you should use Date.

SnakeYAML has plenty of tests with java.util.Date in this format:
"valid iso8601:    2001-12-14t21:59:43.10-05:00"

Please check the tests: 
http://code.google.com/p/snakeyaml/source/browse/src/test/java/org/yaml/snakeyam
l/typ
es/TimestampTagTest.java

Original comment by py4fun@gmail.com on 12 Feb 2010 at 5:15

GoogleCodeExporter commented 9 years ago
Yes, but note:

assertEquals("2001-12-15 at 2:59:43 (100)", getText(
                "valid iso8601:    2001-12-14t21:59:43.10-05:00", "valid iso8601"));

The times and date are different between the left and the right because of the 
-05:00

A Gregorian Date should give you 001-12-14T21:59:43.10-05:00

Original comment by obast...@gmail.com on 12 Feb 2010 at 6:31

GoogleCodeExporter commented 9 years ago
I think I am getting closer...
1) It looks like you wish to pass date/time _and_ timezone together. As if you 
need 
to pass "2+1" or "5-2" instead of simply "3".

2) Currently SnakeYAML can transform the timezone in the YAML document to the 
proper 
Date object. UTC is always used for the opposite way.

3) I think GregorianCalendar should not be represented as a scalar 
(!!timestamp). 
When the parser gets "2001-12-14t21:59:43.10-05:00" in the YAML document how it 
can 
find out which one to use: Date or GregorianCalendar?

4) I think the most convenient way is to write a custom Constructor/Representer 
for 
GregorianCalendar. You can make it either scalar or it can be a JavaBean with 2 
properties: Date and timezone. 

Original comment by py4fun@gmail.com on 12 Feb 2010 at 10:06

GoogleCodeExporter commented 9 years ago
1. Yes, that's true. 

2. Correct. Technically, java is broken, but that's not surprising, dates and 
times are supposed to be simple 
but actually they're hard!

3. That's a good point. The Java Persistence API had to punt, and you have to 
tell it how you want them 
formatted. If you don't want to lose the time zone information, you specify 
Calendar which ends up using 
GregorianCalendar. If you're happy with collapsing it to UTC, you can specify 
timestamp. 

I don't think we have to punt though, because we can solve this with 
introspection. The parser should always 
build a Gregorian Calendar, because then it hasn't lost information yet. As you 
put it, you'll have "5-2". Then, 
in the loader, if the destination wants a Date, you simply call 
calendar.getTime() to convert to UTC, which 
collapses down to "3". If the destination wants a Calendar, you can use the 
GregorianCalendar instead. 

Does that make sense?

4. That would be the most convenient way, and I definitely thought about doing 
that. But then I realized that 
GregorianCalendar was the only java object that didn't lose the timezone 
information, so technically 
SnakeYAML was losing information, and I decided to post an issue instead.  

Original comment by obast...@gmail.com on 12 Feb 2010 at 10:33

GoogleCodeExporter commented 9 years ago
> Then, in the loader, if the destination wants a Date

Unfortunately the parser does not always know the class. (if there is no 
JavaBean and
no explicit tag)
I am afraid treating GregorianCalendar as a timestamp would make SnakeYAML code 
too
complicated.

Can you solve it in your application ? Just add timezone to the document:
---
bean:
  time1: 2001-12-14t21:59:43.10
  time2: 2031-04-14t21:59:43.67
timezone: -05:00
dates:
  - 2001-12-14t21:52:43.10
  - 2001-12-02t21:53:43.14
...

Original comment by aso...@gmail.com on 14 Feb 2010 at 11:53

GoogleCodeExporter commented 9 years ago
I have done a part of the change. The timestamp is parsed as GregorianCalendar.
I have pushed the change to a dedicated repository:
http://code.google.com/r/py4fun-calendar/source/list

This is how the test looks like:
http://code.google.com/r/py4fun-
calendar/source/browse/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarT
est.j
ava?
spec=svn06fd848f608e37b5d03c6e5566b3238c36dc7002&r=06fd848f608e37b5d03c6e5566b32
38c36
dc7002

Can you please test it ?

Dumping GregorianCalendar is still not done since it will affected by issue #47.

Original comment by py4fun@gmail.com on 19 Feb 2010 at 2:26

GoogleCodeExporter commented 9 years ago
While implementing GregorianCalendar serialisation I run into the mess with 
timezones.
Unfortunately the YAML timestamp format cannot be reliably transformed into the
proper time zone.
This is due to the Daylight Saving Time: even the same offset (say GMT-8:00) 
begin
and end DST at different times.
Some info is here:
http://stackoverflow.com/questions/230126/how-to-handle-calendar-timezones-using
-java

I am afraid it makes the whole exercise with GregorianCalendar useless. I am 
not sure
whether it should be implemented.

Original comment by aso...@gmail.com on 22 Feb 2010 at 11:03

GoogleCodeExporter commented 9 years ago
Yeah, I live in Arizona, which doesn't respect DST at all! Believe me, I know 
all about it. BTW, the Navajo 
reservation does use DST, but the Hopi reservation does. You can cross 3 times 
zones in an hour if you do it 
right in AZ!

You'll notice though that the offset takes a date/time to compute the offset 
from, which you're already using. 

It's not perfect, you can still lose information, because you can't tell if 
GMT-7 is AZ or Pacific at certain times 
of the year. But I think you're still closer, because you're not losing the 
offset information. 

But I can see your point. It would almost be better to serialize it as a bean, 
then special case the time zone 
serialization instead. 

Original comment by obast...@gmail.com on 22 Feb 2010 at 4:55

GoogleCodeExporter commented 9 years ago
So I thought about it some more, and here's why I think its ok to serialize 
GregorianCalendar as a timestamp.

I'm coming from the enterprise world, where this time came into/out a database. 
Generally, the whole point 
of a timestamp iso8601, etc. is so that if the user inputs:

 3:00 pm

And you store that away, you want them to see:

 3:00 pm

 later on. So they already have this issue with losing the details of DST, but their solution is basically not to 
care. Databases store time + offset, so that if the user stores 3:00pm they get 
back 3:00pm. That's the part 
they care about, capturing the correct instant in time. Hence ISO8601 which is 
what the yaml timestamp is 
based on, which stores time plus offset from UTC. 

Then we come to dates and times in Java with are both under and over 
engineered. So your choices are 
java.util.Date, which loses the time zone, or GregorianCalendar, which has too 
much information. 

The closest match to the YAML timestamp that's widely available is 
GregorianCalendar. So I think its ok to 
serialize/deserialize it to/from a YAML timestamp. It's true you will lose the 
subtleties between:

timezone: AZ, timezone: MST

but that's a side effect of the timestamp format already. I suspect the 
Ruby/Python/C++ yaml exporters have 
this problem already. 

So I think its ok, because ultimately, you can spit a timestamp out of any 
language (Ruby, Python, etc.) and 
you can serialize it back into Java, and in both cases, you'll get:

3:00 pm. 

That's the important part, capturing and retaining time+offset. 

Original comment by obast...@gmail.com on 22 Feb 2010 at 5:14

GoogleCodeExporter commented 9 years ago
Can the current implementation go to the main repository ?

Original comment by py4fun@gmail.com on 23 Feb 2010 at 4:57

GoogleCodeExporter commented 9 years ago
Yeah, looks good to me. 

Original comment by obast...@gmail.com on 23 Feb 2010 at 10:15

GoogleCodeExporter commented 9 years ago
it will be included in the 1.6 release

Original comment by aso...@gmail.com on 24 Feb 2010 at 8:36

GoogleCodeExporter commented 9 years ago
Doh! I missed this. 

Time zone designator should be hh:mm, so -7:00 should be -07:00. 

Original comment by obast...@gmail.com on 24 Feb 2010 at 10:31

GoogleCodeExporter commented 9 years ago
The YAML specification allows to have any of these:

-7
-07:00
-7:00

http://yaml.org/type/timestamp.html

(([ \t]*)Z|[-+][0-9][0-9]?(:[0-9][0-9])?)? # (time zone)

Original comment by aso...@gmail.com on 25 Feb 2010 at 10:40

GoogleCodeExporter commented 9 years ago
I stand corrected, I was looking at the iso8601 spec. Coolness. 

Original comment by obast...@gmail.com on 25 Feb 2010 at 3:39