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());
+ }
+
+}