Revision: 2867 http://trac.macosforge.org/projects/ruby/changeset/2867 Author: neeracher@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@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
participants (1)
-
source_changes@macosforge.org