Parse GregorianCalendar
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3a0e2fc..de99f53 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -7,7 +7,10 @@
 	</properties>

 	<body>

 	    <release version="1.6" date="in Mercurial" description="introduce Tag class">

-	        <action dev="py4fun" type="fix" issue="51" due-to="johann.Werner">

+	        <action dev="py4fun" type="fix" issue="49" due-to="obastard">

+                Support GregorianCalendar (2010-02-19)

+            </action>

+            <action dev="py4fun" type="fix" issue="51" due-to="johann.Werner">

                 Some Unicode characters are wrongly replaced by \x{fffd} during 

                 double quoted style dump (2010-02-15)

             </action>

diff --git a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
index 945fe7f..41e48d3 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
@@ -25,6 +25,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -399,7 +400,7 @@
                     || type == Boolean.class || Date.class.isAssignableFrom(type)
                     || type == Character.class || type == BigInteger.class
                     || type == BigDecimal.class || Enum.class.isAssignableFrom(type)
-                    || Tag.BINARY.equals(node.getTag())) {
+                    || Tag.BINARY.equals(node.getTag()) || Calendar.class.isAssignableFrom(type)) {
                 // standard classes created directly
                 result = constructStandardJavaInstance(type, node);
             } else {
@@ -516,6 +517,10 @@
                     throw new YAMLException("Unable to find enum value '" + enumValueName
                             + "' for enum class: " + type.getName());
                 }
+            } else if (Calendar.class.isAssignableFrom(type)) {
+                ConstructYamlTimestamp contr = new ConstructYamlTimestamp();
+                contr.construct(node);
+                result = contr.getCalendar();
             } else {
                 throw new YAMLException("Unsupported class: " + type);
             }
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
index ad384e3..1e2f011 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
@@ -255,7 +255,13 @@
     private final static Pattern YMD_REGEXP = Pattern

             .compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");

 

-    private class ConstructYamlTimestamp extends AbstractConstruct {

+    protected class ConstructYamlTimestamp extends AbstractConstruct {

+        private Calendar calendar;

+

+        public Calendar getCalendar() {

+            return calendar;

+        }

+

         public Object construct(Node node) {

             ScalarNode scalar = (ScalarNode) node;

             String nodeValue = scalar.getValue();

@@ -264,13 +270,13 @@
                 String year_s = match.group(1);

                 String month_s = match.group(2);

                 String day_s = match.group(3);

-                Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

-                cal.clear();

-                cal.set(Calendar.YEAR, Integer.parseInt(year_s));

+                calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

+                calendar.clear();

+                calendar.set(Calendar.YEAR, Integer.parseInt(year_s));

                 // Java's months are zero-based...

-                cal.set(Calendar.MONTH, Integer.parseInt(month_s) - 1); // x

-                cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));

-                return cal.getTime();

+                calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1); // x

+                calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));

+                return calendar.getTime();

             } else {

                 match = TIMESTAMP_REGEXP.matcher(nodeValue);

                 if (!match.matches()) {

@@ -295,31 +301,24 @@
                         }

                     }

                 }

-                Calendar cal = Calendar.getInstance();

-                cal.set(Calendar.YEAR, Integer.parseInt(year_s));

-                // Java's months are zero-based...

-                cal.set(Calendar.MONTH, Integer.parseInt(month_s) - 1);

-                cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));

-                cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour_s));

-                cal.set(Calendar.MINUTE, Integer.parseInt(min_s));

-                cal.set(Calendar.SECOND, Integer.parseInt(sec_s));

-                cal.set(Calendar.MILLISECOND, usec);

+                TimeZone timeZone;

                 if (timezoneh_s != null) {

-                    int zone = 0;

-                    int sign = +1;

-                    if (timezoneh_s.startsWith("-")) {

-                        sign = -1;

-                    }

-                    zone += Integer.parseInt(timezoneh_s.substring(1)) * 3600000;

-                    if (timezonem_s != null) {

-                        zone += Integer.parseInt(timezonem_s) * 60000;

-                    }

-                    cal.set(Calendar.ZONE_OFFSET, sign * zone);

+                    String time = timezonem_s != null ? ":" + timezonem_s : "00";

+                    timeZone = TimeZone.getTimeZone("GMT" + timezoneh_s + time);

                 } else {

                     // no time zone provided

-                    cal.setTimeZone(TimeZone.getTimeZone("UTC"));

+                    timeZone = TimeZone.getTimeZone("UTC");

                 }

-                return cal.getTime();

+                calendar = Calendar.getInstance(timeZone);

+                calendar.set(Calendar.YEAR, Integer.parseInt(year_s));

+                // Java's months are zero-based...

+                calendar.set(Calendar.MONTH, Integer.parseInt(month_s) - 1);

+                calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day_s));

+                calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour_s));

+                calendar.set(Calendar.MINUTE, Integer.parseInt(min_s));

+                calendar.set(Calendar.SECOND, Integer.parseInt(sec_s));

+                calendar.set(Calendar.MILLISECOND, usec);

+                return calendar.getTime();

             }

         }

     }

diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarBean.java b/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarBean.java
new file mode 100644
index 0000000..ececf1d
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarBean.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2008-2010 Andrey Somov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.yaml.snakeyaml.issues.issue49;
+
+import java.util.Calendar;
+
+public class CalendarBean {
+    private Calendar calendar;
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Calendar getCalendar() {
+        return calendar;
+    }
+
+    public void setCalendar(Calendar calendar) {
+        this.calendar = calendar;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarTest.java
new file mode 100644
index 0000000..c9484cd
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue49/CalendarTest.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2008-2010 Andrey Somov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.yaml.snakeyaml.issues.issue49;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.JavaBeanDumper;
+import org.yaml.snakeyaml.JavaBeanLoader;
+import org.yaml.snakeyaml.Yaml;
+
+public class CalendarTest extends TestCase {
+    public void testDump() {
+        CalendarBean bean = new CalendarBean();
+        bean.setName("lunch");
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(new Date(1000000000000L));
+        cal.setTimeZone(TimeZone.getTimeZone("GMT-8:00"));
+        bean.setCalendar(cal);
+        JavaBeanDumper yaml = new JavaBeanDumper();
+        String output = yaml.dump(bean);
+        // System.out.println(output);
+        // TODO assertEquals("???", output);
+        assertTrue(output, output.startsWith("calendar: !!java.util.GregorianCalendar"));
+    }
+
+    public void testLoadBean() {
+        JavaBeanLoader<CalendarBean> beanLoader = new JavaBeanLoader<CalendarBean>(
+                CalendarBean.class);
+        CalendarBean bean = beanLoader
+                .load("calendar:  2001-12-14t21:59:43.10-05:00\nname: dinner");
+        assertEquals("dinner", bean.getName());
+        Calendar calendar = bean.getCalendar();
+        assertEquals(TimeZone.getTimeZone("GMT-5:00").getOffset(calendar.getTime().getTime()),
+                calendar.getTimeZone().getOffset(calendar.getTime().getTime()));
+        //
+        Yaml yaml = new Yaml();
+        Date date = (Date) yaml.load("2001-12-14t21:59:43.10-05:00");
+        assertEquals(date, calendar.getTime());
+    }
+
+    public void testLoadWithTag() {
+        Yaml yaml = new Yaml();
+        GregorianCalendar calendar = (GregorianCalendar) yaml
+                .load("!!java.util.GregorianCalendar 2001-12-14t21:59:43.10-05:00");
+        assertEquals(TimeZone.getTimeZone("GMT-5:00").getOffset(calendar.getTime().getTime()),
+                calendar.getTimeZone().getOffset(calendar.getTime().getTime()));
+        //
+        Date date = (Date) yaml.load("2001-12-14t21:59:43.10-05:00");
+        assertEquals(date, calendar.getTime());
+    }
+
+}