[macruby-changes] [2867] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Oct 20 01:09:11 PDT 2009


Revision: 2867
          http://trac.macosforge.org/projects/ruby/changeset/2867
Author:   neeracher at apple.com
Date:     2009-10-20 01:09:07 -0700 (Tue, 20 Oct 2009)
Log Message:
-----------
Implement YAML support for date/time

Modified Paths:
--------------
    MacRuby/trunk/ext/libyaml/rubyext.c
    MacRuby/trunk/lib/yaml/rubytypes.rb
    MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/to_yaml_tags.txt

Removed Paths:
-------------
    MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/load_tags.txt

Modified: MacRuby/trunk/ext/libyaml/rubyext.c
===================================================================
--- MacRuby/trunk/ext/libyaml/rubyext.c	2009-10-20 07:05:21 UTC (rev 2866)
+++ MacRuby/trunk/ext/libyaml/rubyext.c	2009-10-20 08:09:07 UTC (rev 2867)
@@ -359,6 +359,121 @@
     return true;
 }
 
+static inline bool
+is_timestamp(const char *str, size_t length)
+{
+  // TODO: This probably should be coded as a regex and/or in ruby
+  bool canonical = true;
+  if (length < 10) {
+    return false;
+  }
+  /* 4 digit year - */
+  if (!isdigit(str[0]) ||
+      !isdigit(str[1]) ||
+      !isdigit(str[2]) ||
+      !isdigit(str[3]) ||
+      str[4] != '-') {
+    return false;
+  }
+  str += 5;
+  /* 1/2 digit month - */
+  if (!isdigit(*str++)) {
+    return false;
+  }
+  if (isdigit(*str)) {
+    ++str;
+  }
+  else {
+    canonical = false;
+  } 
+  if (*str++ != '-') {
+    return false;
+  }
+  /* 1/2 digit day */
+  if (!isdigit(*str++)) {
+    return false;
+  }
+  if (isdigit(*str)) {
+    ++str;
+  }
+  else {
+    canonical = false;
+  } 
+  /* Date alone must be YYYY-MM-DD */
+  if (*str == '\0') {
+    return canonical;
+  }
+  else if (*str == 't' || *str == 'T') {
+    ++str;
+  }
+  else if (*str == ' ' || *str == '\t') {
+    do {
+      ++str;
+    } while (*str == ' ' || *str == '\t');
+  } 
+  else {
+    return false;
+  }
+  /* 1/2 digit hour : */
+  if (!isdigit(*str++)) {
+    return false;
+  }
+  if (isdigit(*str)) {
+    ++str;
+  }
+  if (*str++ != ':') {
+    return false;
+  }
+  /* 2 digit minute:second */
+  if (!isdigit(str[0]) ||
+      !isdigit(str[1]) ||
+      (str[2] != ':')  ||
+      !isdigit(str[3]) ||
+      !isdigit(str[4])) {
+    return false;
+  }
+  str += 5;
+  /* Optional fraction */
+  if (*str == '.') {
+    do {
+      ++str;
+    } while (isdigit(*str));
+  }
+  if (*str == '\0') {
+    return true; /* Assumed UTC */
+  }
+  while (*str == ' ' || *str == '\t') {
+    ++str;
+  }
+  if (str[0] == 'Z' && str[1] == '\0') {
+    return true; /* UTC */
+  }
+  else if (str[0] != '+' && str[0] != '-') {
+    return false;
+  }
+  ++str;
+  /* 1/2 digit time zone hour */
+  if (!isdigit(*str++)) {
+    return false;
+  }
+  if (isdigit(*str)) {
+    ++str;
+  }
+  if (*str == '\0') {
+    return true;
+  }
+  /* Optional minute */
+  if ((str[0] != ':')  ||
+      !isdigit(str[1]) ||
+      !isdigit(str[2]) ||
+      (str[3] != '\0')) {
+    return false;
+  }
+  else {
+    return true; 
+  }
+}
+
 static char *
 detect_scalar_type(const char * val, size_t length)
 {
@@ -380,6 +495,9 @@
   else if (strcmp(val, "false") == 0) {
     return "tag:yaml.org,2002:false";
   }
+  else if (is_timestamp(val, length)) {
+    return "tag:yaml.org,2002:timestamp";
+  }
   else {
     return NULL;
   }
@@ -576,6 +694,7 @@
 	    (strcmp(tag, "tag:yaml.org,2002:true") == 0) ||
 	    (strcmp(tag, "tag:yaml.org,2002:false") == 0) ||
 	    (strcmp(tag, "tag:yaml.org,2002:null") == 0) ||
+	    (strcmp(tag, "tag:yaml.org,2002:timestamp") == 0) ||
 	    (strcmp(tag, YAML_DEFAULT_SEQUENCE_TAG) == 0) ||
 	    (strcmp(tag, YAML_DEFAULT_MAPPING_TAG) == 0)) {
 	*can_omit_tag = 1;

Modified: MacRuby/trunk/lib/yaml/rubytypes.rb
===================================================================
--- MacRuby/trunk/lib/yaml/rubytypes.rb	2009-10-20 07:05:21 UTC (rev 2866)
+++ MacRuby/trunk/lib/yaml/rubytypes.rb	2009-10-20 08:09:07 UTC (rev 2867)
@@ -1,5 +1,5 @@
 # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
-# require 'date'
+require 'date'
 require 'libyaml'
 
 class Class
@@ -258,7 +258,69 @@
   end
 end
 
+class DateTime
+    yaml_as "tag:yaml.org,2002:timestamp"
+    def self.yaml_new(val)
+        if val.length <= 10
+            Date.strptime(val)
+        else
+            format = "%F %T"
+            if val =~ /([tT])/
+                format = "%F#{$1}%T"
+            end
+            if val =~ /\./
+                format += ".%N%z"
+            else
+                format += "%z"
+            end
+            val = val.tr(" \t", "")
+            if val !~ /(Z|[-+]\d\d?(?::\d\d)?)$/
+                val = val + "Z"
+            end
+            strptime(val, format).to_time
+        end
+    end
+    def to_yaml(output = nil)
+        to_time.to_yaml(output)
+    end
+end
 
+class Time
+	def to_yaml(output = nil)
+        # Not exactly canonical YAML format, but legal, and consistent with syck
+		YAML::quick_emit(output) do |out|
+            tz = "Z"
+            # from the tidy Tobias Peters <t-peters at gmx.de> Thanks!
+            unless self.utc?
+                utc_same_instant = self.dup.utc
+                utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec)
+                difference_to_utc = utc_same_writing - utc_same_instant
+                if (difference_to_utc < 0) 
+                    difference_sign = '-'
+                    absolute_difference = -difference_to_utc
+                else
+                    difference_sign = '+'
+                    absolute_difference = difference_to_utc
+                end
+                difference_minutes = (absolute_difference/60).round
+                tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
+            end
+            standard = self.strftime( "%Y-%m-%d %H:%M:%S" )
+            standard += ".%06d" % [usec] if usec.nonzero?
+            standard += " %s" % [tz]
+            out.scalar("tag:yaml.org,2002:timestamp", standard, :plain)
+        end
+	end
+end
+
+class Date
+	def to_yaml(output = nil)
+		YAML::quick_emit(output) do |out|
+            out.scalar("tag:yaml.org,2002:timestamp", self.to_s, :plain)
+        end
+	end
+end
+
 =begin
 
 class Hash

Deleted: MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/load_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/load_tags.txt	2009-10-20 07:05:21 UTC (rev 2866)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/load_tags.txt	2009-10-20 08:09:07 UTC (rev 2867)
@@ -1 +0,0 @@
-fails:YAML.load works on complex keys

Modified: MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/to_yaml_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/to_yaml_tags.txt	2009-10-20 07:05:21 UTC (rev 2866)
+++ MacRuby/trunk/spec/frozen/tags/macruby/library/yaml/to_yaml_tags.txt	2009-10-20 08:09:07 UTC (rev 2867)
@@ -1,7 +1,4 @@
 fails:Object#to_yaml returns the YAML representation of a Struct object
-fails:Object#to_yaml returns the YAML representation of an Array object
-fails:Object#to_yaml returns the YAML representation of a Date object
 fails:Object#to_yaml returns the YAML represenation of a RegExp object
-fails:Object#to_yaml returns the YAML representation of a Time object
 fails:Object#to_yaml returns the YAML representation of a Error object
 fails:Object#to_yaml returns the YAML representation for Range objects
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091020/3e831ecd/attachment-0001.html>


More information about the macruby-changes mailing list