yarv-diff:419
From: ko1 atdot.net
Date: 31 Dec 2006 17:05:23 +0900
Subject: [yarv-diff:419] r588 - in trunk: . lib lib/date sample
Author: ko1
Date: 2006-12-31 17:05:21 +0900 (Sun, 31 Dec 2006)
New Revision: 588
Removed:
trunk/lib/date2.rb
Modified:
trunk/ChangeLog
trunk/Makefile.in
trunk/array.c
trunk/configure.in
trunk/dir.c
trunk/enum.c
trunk/eval.c
trunk/file.c
trunk/instruby.rb
trunk/intern.h
trunk/io.c
trunk/lib/README
trunk/lib/date.rb
trunk/lib/date/format.rb
trunk/object.c
trunk/ruby.h
trunk/rubytest.rb
trunk/sample/test.rb
trunk/string.c
trunk/variable.c
Log:
* catch up ruby/trunk 11437
* eval_intern.h : reorder tag initialization
* eval.c : fix to support __send!, funcall and prohibit funcall as
send
* eval_error.h, eval_jump.h, eval_safe.h : fix prototypes
* eval_method.h, vm.c : check re-definition at rb_add_method()
* yarvcore.h : fix typo
* compile.c : fix white spaces
* lib/delegate.rb : fix to support __send, ...
* lib/getoptlong.rb : fix to work on YARV
* lib/rss/parser.rb : use __send! instead of __send__
* sample/test.rb : comment out codes which use |&b| type block parameter
* ext/ripper/extconf.rb : turn off
* test/ripper/test_files.rb, test_parser_events.rb,
test_scanner_events.rb : fix to check it has ripper module
* vm_dump.c : remove showing file path length limitation
* yarvtest/test_eval.rb : use __send! instead of __send__
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/ChangeLog 2006-12-31 08:05:21 UTC (rev 588)
@@ -6,6 +6,8 @@
2006-12-30(Sat) 07:59:26 +0900 Koichi Sasada <ko1 atdot.net>
+ * catch up ruby/trunk 11437
+
* eval_intern.h : reorder tag initialization
* eval.c : fix to support __send!, funcall and prohibit funcall as
Modified: trunk/Makefile.in
===================================================================
--- trunk/Makefile.in 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/Makefile.in 2006-12-31 08:05:21 UTC (rev 588)
@@ -1,4 +1,5 @@
SHELL = /bin/sh
+NULLCMD = :
#### Start of system configuration section. ####
Modified: trunk/array.c
===================================================================
--- trunk/array.c 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/array.c 2006-12-31 08:05:21 UTC (rev 588)
@@ -39,7 +39,15 @@
}
}
-#define ARY_TMPLOCK FL_USER1
+#define ARY_ITERLOCK FL_USER1
+static void
+ary_iter_check(VALUE ary)
+{
+ if (FL_TEST(ary, ARY_ITERLOCK)) {
+ rb_raise(rb_eRuntimeError, "can't modify array during iteration");
+ }
+}
+#define ARY_SORTLOCK FL_USER3
#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)
#define ARY_SET_LEN(ary, n) do { \
@@ -52,6 +60,11 @@
RARRAY(ary)->aux.capa = (capacity);\
} while (0)
+#define ITERATE(func, ary) do { \
+ FL_SET(ary, ARY_ITERLOCK); \
+ return rb_ensure(func, (ary), each_unlock, (ary));\
+} while (0)
+
static VALUE *
rb_ary_ptr(VALUE ary)
{
@@ -62,8 +75,8 @@
rb_ary_modify_check(VALUE ary)
{
if (OBJ_FROZEN(ary)) rb_error_frozen("array");
- if (FL_TEST(ary, ARY_TMPLOCK))
- rb_raise(rb_eRuntimeError, "can't modify array during iteration");
+ if (FL_TEST(ary, ARY_SORTLOCK))
+ rb_raise(rb_eRuntimeError, "can't modify array during sort");
if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
@@ -101,7 +114,7 @@
rb_ary_frozen_p(VALUE ary)
{
if (OBJ_FROZEN(ary)) return Qtrue;
- if (FL_TEST(ary, ARY_TMPLOCK)) return Qtrue;
+ if (FL_TEST(ary, ARY_SORTLOCK)) return Qtrue;
return Qfalse;
}
@@ -282,6 +295,7 @@
VALUE size, val;
rb_ary_modify(ary);
+ ary_iter_check(ary);
if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
free(RARRAY(ary)->ptr);
@@ -522,6 +536,7 @@
VALUE top;
rb_ary_modify_check(ary);
+ ary_iter_check(ary);
if (RARRAY_LEN(ary) == 0) return Qnil;
top = RARRAY_PTR(ary)[0];
if (!ARY_SHARED_P(ary)) {
@@ -567,6 +582,7 @@
}
rb_ary_modify_check(ary);
+ ary_iter_check(ary);
result = ary_shared_first(argc, argv, ary, Qfalse);
n = RARRAY_LEN(result);
if (ARY_SHARED_P(ary)) {
@@ -600,6 +616,7 @@
if (argc == 0) return ary;
rb_ary_modify(ary);
+ ary_iter_check(ary);
if (RARRAY(ary)->aux.capa <= RARRAY_LEN(ary)+argc) {
RESIZE_CAPA(ary, RARRAY(ary)->aux.capa + ARY_DEFAULT_SIZE);
}
@@ -912,8 +929,8 @@
long i = RARRAY_LEN(ary);
if (rb_scan_args(argc, argv, "01", &val) == 0) {
+ RETURN_ENUMERATOR(ary, 0, 0);
while (i--) {
- RETURN_ENUMERATOR(ary, 0, 0);
if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
return LONG2NUM(i);
if (i > RARRAY_LEN(ary)) {
@@ -970,6 +987,7 @@
rlen = RARRAY_LEN(rpl);
}
rb_ary_modify(ary);
+ ary_iter_check(ary);
if (beg >= RARRAY_LEN(ary)) {
len = beg + rlen;
if (len >= ARY_CAPA(ary)) {
@@ -1092,6 +1110,24 @@
return ary;
}
+static VALUE
+each_unlock(VALUE ary)
+{
+ FL_UNSET(ary, ARY_ITERLOCK);
+ return ary;
+}
+
+static VALUE
+each_i(VALUE ary)
+{
+ long i;
+
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ rb_yield(RARRAY_PTR(ary)[i]);
+ }
+ return ary;
+}
+
/*
* call-seq:
* array.each {|item| block } -> array
@@ -1122,8 +1158,17 @@
return val;
}
+ ITERATE(each_i, ary);
+ return ary;
+}
+
+static VALUE
+each_index_i(VALUE ary)
+{
+ long i;
+
for (i=0; i<RARRAY_LEN(ary); i++) {
- rb_yield(RARRAY_PTR(ary)[i]);
+ rb_yield(LONG2NUM(i));
}
return ary;
}
@@ -1146,11 +1191,20 @@
static VALUE
rb_ary_each_index(VALUE ary)
{
- long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ ITERATE(each_index_i, ary);
+}
- RETURN_ENUMERATOR(ary, 0, 0);
- for (i=0; i<RARRAY_LEN(ary); i++) {
- rb_yield(LONG2NUM(i));
+static VALUE
+reverse_each_i(VALUE ary)
+{
+ long len = RARRAY_LEN(ary);
+
+ while (len--) {
+ rb_yield(RARRAY_PTR(ary)[len]);
+ if (RARRAY_LEN(ary) < len) {
+ len = RARRAY_LEN(ary);
+ }
}
return ary;
}
@@ -1173,16 +1227,8 @@
static VALUE
rb_ary_reverse_each(VALUE ary)
{
- long len = RARRAY_LEN(ary);
-
RETURN_ENUMERATOR(ary, 0, 0);
- while (len--) {
- rb_yield(RARRAY_PTR(ary)[len]);
- if (RARRAY_LEN(ary) < len) {
- len = RARRAY_LEN(ary);
- }
- }
- return ary;
+ ITERATE(reverse_each_i, ary);
}
/*
@@ -1390,6 +1436,7 @@
VALUE tmp;
rb_ary_modify(ary);
+ ary_iter_check(ary);
if (RARRAY_LEN(ary) > 1) {
p1 = RARRAY_PTR(ary);
p2 = p1 + RARRAY_LEN(ary) - 1; /* points last item */
@@ -1486,7 +1533,7 @@
}
static VALUE
-sort_internal(VALUE ary)
+sort_i(VALUE ary)
{
struct ary_sort_data data;
@@ -1500,7 +1547,7 @@
static VALUE
sort_unlock(VALUE ary)
{
- FL_UNSET(ary, ARY_TMPLOCK);
+ FL_UNSET(ary, ARY_SORTLOCK);
return ary;
}
@@ -1524,9 +1571,10 @@
rb_ary_sort_bang(VALUE ary)
{
rb_ary_modify(ary);
+ ary_iter_check(ary);
if (RARRAY_LEN(ary) > 1) {
- FL_SET(ary, ARY_TMPLOCK); /* prohibit modification during sort */
- rb_ensure(sort_internal, ary, sort_unlock, ary);
+ FL_SET(ary, ARY_SORTLOCK); /* prohibit modification during sort */
+ rb_ensure(sort_i, ary, sort_unlock, ary);
}
return ary;
}
@@ -1555,6 +1603,20 @@
return ary;
}
+
+static VALUE
+collect_i(VALUE ary)
+{
+ long i;
+ VALUE collect;
+
+ collect = rb_ary_new2(RARRAY_LEN(ary));
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
+ }
+ return collect;
+}
+
/*
* call-seq:
* array.collect {|item| block } -> an_array
@@ -1572,15 +1634,21 @@
static VALUE
rb_ary_collect(VALUE ary)
{
+ RETURN_ENUMERATOR(ary, 0, 0);
+ ITERATE(collect_i, ary);
+}
+
+
+static VALUE
+collect_bang_i(VALUE ary)
+{
long i;
- VALUE collect;
- RETURN_ENUMERATOR(ary, 0, 0);
- collect = rb_ary_new2(RARRAY_LEN(ary));
+ rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
+ RARRAY_PTR(ary)[i] = rb_yield(RARRAY_PTR(ary)[i]);
}
- return collect;
+ return ary;
}
/*
@@ -1600,14 +1668,8 @@
static VALUE
rb_ary_collect_bang(VALUE ary)
{
- long i;
-
RETURN_ENUMERATOR(ary, 0, 0);
- rb_ary_modify(ary);
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
- }
- return ary;
+ ITERATE(collect_bang_i, ary);
}
VALUE
@@ -1660,6 +1722,22 @@
return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
}
+
+static VALUE
+select_i(VALUE ary)
+{
+ VALUE result;
+ long i;
+
+ result = rb_ary_new2(RARRAY_LEN(ary));
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
+ rb_ary_push(result, rb_ary_elt(ary, i));
+ }
+ }
+ return result;
+}
+
/*
* call-seq:
* array.select {|item| block } -> an_array
@@ -1675,17 +1753,8 @@
static VALUE
rb_ary_select(VALUE ary)
{
- VALUE result;
- long i;
-
RETURN_ENUMERATOR(ary, 0, 0);
- result = rb_ary_new2(RARRAY_LEN(ary));
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
- rb_ary_push(result, rb_ary_elt(ary, i));
- }
- }
- return result;
+ ITERATE(select_i, ary);
}
/*
@@ -1727,6 +1796,7 @@
}
rb_ary_modify(ary);
+ ary_iter_check(ary);
if (RARRAY_LEN(ary) > i2) {
RARRAY(ary)->len = i2;
if (i2 * 2 < ARY_CAPA(ary) &&
@@ -1751,6 +1821,7 @@
}
rb_ary_modify(ary);
+ ary_iter_check(ary);
del = RARRAY_PTR(ary)[pos];
MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
RARRAY_LEN(ary)-pos-1);
@@ -1829,22 +1900,11 @@
return rb_ary_delete_at(ary, NUM2LONG(arg1));
}
-/*
- * call-seq:
- * array.reject! {|item| block } -> array or nil
- *
- * Equivalent to <code>Array#delete_if</code>, deleting elements from
- * _self_ for which the block evaluates to true, but returns
- * <code>nil</code> if no changes were made. Also see
- * <code>Enumerable#reject</code>.
- */
-
static VALUE
-rb_ary_reject_bang(VALUE ary)
+reject_bang_i(VALUE ary)
{
long i1, i2;
- RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
VALUE v = RARRAY_PTR(ary)[i1];
@@ -1854,15 +1914,33 @@
}
i2++;
}
+
if (RARRAY_LEN(ary) == i2) return Qnil;
if (i2 < RARRAY_LEN(ary))
RARRAY(ary)->len = i2;
-
return ary;
}
/*
* call-seq:
+ * array.reject! {|item| block } -> array or nil
+ *
+ * Equivalent to <code>Array#delete_if</code>, deleting elements from
+ * _self_ for which the block evaluates to true, but returns
+ * <code>nil</code> if no changes were made. Also see
+ * <code>Enumerable#reject</code>.
+ */
+
+static VALUE
+rb_ary_reject_bang(VALUE ary)
+{
+ RETURN_ENUMERATOR(ary, 0, 0);
+ ary_iter_check(ary);
+ ITERATE(reject_bang_i, ary);
+}
+
+/*
+ * call-seq:
* array.reject {|item| block } -> an_array
*
* Returns a new array containing the items in _self_
@@ -1925,6 +2003,7 @@
long len;
VALUE result;
+ RETURN_ENUMERATOR(ary, argc, argv);
for (i=0; i<argc; i++) {
argv[i] = to_a(argv[i]);
}
@@ -2012,6 +2091,7 @@
VALUE *ptr;
rb_ary_modify(copy);
+ ary_iter_check(copy);
orig = to_ary(orig);
if (copy == orig) return copy;
shared = ary_make_shared(orig);
@@ -2039,6 +2119,7 @@
rb_ary_clear(VALUE ary)
{
rb_ary_modify(ary);
+ ary_iter_check(ary);
RARRAY(ary)->len = 0;
if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2);
@@ -2106,6 +2187,7 @@
break;
}
rb_ary_modify(ary);
+ ary_iter_check(ary);
end = beg + len;
if (end > RARRAY_LEN(ary)) {
if (end >= ARY_CAPA(ary)) {
@@ -2587,6 +2669,7 @@
VALUE hash, v, vv;
long i, j;
+ ary_iter_check(ary);
hash = ary_make_hash(ary, 0);
if (RARRAY_LEN(ary) == RHASH(hash)->tbl->num_entries) {
@@ -2639,6 +2722,7 @@
long n;
rb_ary_modify(ary);
+ ary_iter_check(ary);
p = t = RARRAY_PTR(ary);
end = p + RARRAY_LEN(ary);
@@ -2832,6 +2916,8 @@
{
long i = RARRAY_LEN(ary);
+ rb_ary_modify(ary);
+ ary_iter_check(ary);
while (i) {
long j = genrand_real()*i;
VALUE tmp = RARRAY_PTR(ary)[--i];
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/configure.in 2006-12-31 08:05:21 UTC (rev 588)
@@ -1534,7 +1534,7 @@
[ --with-sitedir=DIR site libraries in DIR [PREFIX/lib/ruby/site_ruby]],
[sitedir=$withval],
[sitedir='${prefix}/lib/ruby/site_ruby'])
-SITE_DIR="`eval \"echo ${sitedir}\"`"
+SITE_DIR=`eval echo \\"${sitedir}\\"`
case "$target_os" in
cygwin*|mingw*|*djgpp*|os2-emx*)
RUBY_SITE_LIB_PATH="`expr "$SITE_DIR" : "$prefix\(/.*\)"`" ||
Modified: trunk/dir.c
===================================================================
--- trunk/dir.c 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/dir.c 2006-12-31 08:05:21 UTC (rev 588)
@@ -1896,6 +1896,7 @@
rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1);
+ rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1); /* in file.c */
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
Modified: trunk/enum.c
===================================================================
--- trunk/enum.c 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/enum.c 2006-12-31 08:05:21 UTC (rev 588)
@@ -335,13 +335,14 @@
}
static VALUE
-inject_i(VALUE i, VALUE *memo)
+inject_i(VALUE i, VALUE memo)
{
- if (*memo == Qundef) {
- *memo = i;
+ if (RARRAY_PTR(memo)[0] == Qundef) {
+ RARRAY_PTR(memo)[0] = i;
}
else {
- *memo = rb_yield_values(2, *memo, i);
+ RARRAY_PTR(memo)[1] = i;
+ RARRAY_PTR(memo)[0] = rb_yield(memo);
}
return Qnil;
}
@@ -380,13 +381,18 @@
static VALUE
enum_inject(int argc, VALUE *argv, VALUE obj)
{
- VALUE memo = Qundef;
+ VALUE memo, tmp;
- if (rb_scan_args(argc, argv, "01", &memo) == 0)
- memo = Qundef;
- rb_block_call(obj, id_each, 0, 0, inject_i, (VALUE)&memo);
- if (memo == Qundef) return Qnil;
- return memo;
+ if (rb_scan_args(argc, argv, "01", &tmp) == 0) {
+ memo = rb_ary_new3(2, Qundef, Qnil);
+ }
+ else {
+ memo = rb_ary_new3(2, tmp, Qnil);
+ }
+ rb_block_call(obj, id_each, 0, 0, inject_i, (VALUE)memo);
+ tmp = RARRAY_PTR(memo)[0];
+ if (tmp == Qundef) return Qnil;
+ return tmp;
}
static VALUE
@@ -881,7 +887,10 @@
*memo = i;
}
else {
- cmp = rb_yield_values(2, i, *memo);
+ VALUE ary = memo[1];
+ RARRAY_PTR(ary)[0] = i;
+ RARRAY_PTR(ary)[1] = *memo;
+ cmp = rb_yield(ary);
if (rb_cmpint(cmp, i, *memo) < 0) {
*memo = i;
}
@@ -907,11 +916,18 @@
static VALUE
enum_min(VALUE obj)
{
- VALUE result = Qundef;
+ VALUE result[2];
- rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? min_ii : min_i, (VALUE)&result);
- if (result == Qundef) return Qnil;
- return result;
+ result[0] = Qundef;
+ if (rb_block_given_p()) {
+ result[1] = rb_ary_new3(2, Qnil, Qnil);
+ rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)result);
+ }
+ else {
+ rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)result);
+ }
+ if (result[0] == Qundef) return Qnil;
+ return result[0];
}
static VALUE
@@ -940,7 +956,10 @@
*memo = i;
}
else {
- cmp = rb_yield_values(2, i, *memo);
+ VALUE ary = memo[1];
+ RARRAY_PTR(ary)[0] = i;
+ RARRAY_PTR(ary)[1] = *memo;
+ cmp = rb_yield(ary);
if (rb_cmpint(cmp, i, *memo) > 0) {
*memo = i;
}
@@ -965,11 +984,18 @@
static VALUE
enum_max(VALUE obj)
{
- VALUE result = Qundef;
+ VALUE result[2];
- rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? max_ii : max_i, (VALUE)&result);
- if (result == Qundef) return Qnil;
- return result;
+ result[0] = Qundef;
+ if (rb_block_given_p()) {
+ result[1] = rb_ary_new3(2, Qnil, Qnil);
+ rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)result);
+ }
+ else {
+ rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)result);
+ }
+ if (result[0] == Qundef) return Qnil;
+ return result[0];
}
static VALUE
@@ -1089,10 +1115,16 @@
}
static VALUE
-each_with_index_i(VALUE val, VALUE *memo)
+each_with_index_i(VALUE val, VALUE memo)
{
- rb_yield_values(2, val, INT2FIX(*memo));
- ++*memo;
+ long n;
+
+ RARRAY_PTR(memo)[0] = val;
+ rb_yield(memo);
+ val = RARRAY_PTR(memo)[1];
+ n = NUM2LONG(val);
+ n++;
+ RARRAY_PTR(memo)[1] = INT2NUM(n);
return Qnil;
}
@@ -1114,11 +1146,12 @@
static VALUE
enum_each_with_index(VALUE obj)
{
- VALUE memo = 0;
+ VALUE memo;
RETURN_ENUMERATOR(obj, 0, 0);
- rb_block_call(obj, id_each, 0, 0, each_with_index_i, (VALUE)&memo);
+ memo = rb_ary_new3(2, Qnil, INT2FIX(0));
+ rb_block_call(obj, id_each, 0, 0, each_with_index_i, memo);
return obj;
}
Modified: trunk/eval.c
===================================================================
--- trunk/eval.c 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/eval.c 2006-12-31 08:05:21 UTC (rev 588)
@@ -405,13 +405,17 @@
*/
static VALUE
-rb_mod_s_constants(void)
+rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
{
NODE *cref = ruby_cref();
VALUE klass;
VALUE cbase = 0;
void *data = 0;
+ if (argc > 0) {
+ return rb_mod_constants(argc, argv, rb_cModule);
+ }
+
while (cref) {
klass = cref->nd_clss;
if (!NIL_P(klass)) {
@@ -2893,27 +2897,19 @@
rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
rb_define_method(rb_mKernel, "instance_exec", rb_obj_instance_exec, -1);
- rb_define_private_method(rb_cModule, "append_features",
- rb_mod_append_features, 1);
- rb_define_private_method(rb_cModule, "extend_object",
- rb_mod_extend_object, 1);
+ rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
+ rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
- rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc,
- -1);
+ rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
- rb_define_method(rb_cModule, "public_method_defined?",
- rb_mod_public_method_defined, 1);
- rb_define_method(rb_cModule, "private_method_defined?",
- rb_mod_private_method_defined, 1);
- rb_define_method(rb_cModule, "protected_method_defined?",
- rb_mod_protected_method_defined, 1);
- rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method,
- -1);
- rb_define_method(rb_cModule, "private_class_method",
- rb_mod_private_method, -1);
+ rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
+ rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
+ rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
+ rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
+ rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
@@ -2921,16 +2917,12 @@
rb_undef_method(rb_cClass, "module_function");
- rb_define_private_method(rb_cModule, "remove_method",
- rb_mod_remove_method, -1);
- rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method,
- -1);
- rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method,
- 2);
+ rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
+ rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
+ rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
- rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants,
- 0);
+ rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
Modified: trunk/file.c
===================================================================
--- trunk/file.c 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/file.c 2006-12-31 08:05:21 UTC (rev 588)
@@ -789,7 +789,7 @@
group_member(GETGROUPS_T gid)
{
#ifndef _WIN32
- if (getgid() == gid)
+ if (getgid() == gid || getegid() == gid)
return Qtrue;
# ifdef HAVE_GETGROUPS
@@ -849,7 +849,7 @@
if (st.st_uid == euid) /* owner */
mode <<= 6;
- else if (getegid() == st.st_gid || group_member(st.st_gid))
+ else if (group_member(st.st_gid))
mode <<= 3;
if ((st.st_mode & mode) == mode) return 0;
@@ -877,7 +877,30 @@
/*
+ * File.directory?(file_name) => true or false
+ * File.directory?(file_name) => true or false
+ *
+ * Returns <code>true</code> if the named file is a directory,
+ * <code>false</code> otherwise.
+ *
+ * File.directory?(".")
+ */
+
+/*
+ * Document-method: exist?
+ *
* call-seq:
+ * Dir.exist?(file_name) => true or false
+ *
+ * Returns <code>true</code> if the named file is a directory,
+ * <code>false</code> otherwise.
+ *
+ */
+
+/*
+ * Document-method: directory?
+ *
+ * call-seq:
* File.directory?(file_name) => true or false
*
* Returns <code>true</code> if the named file is a directory,
@@ -886,8 +909,8 @@
* File.directory?(".")
*/
-static VALUE
-test_d(VALUE obj, VALUE fname)
+VALUE
+rb_file_directory_p(VALUE obj, VALUE fname)
{
#ifndef S_ISDIR
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
@@ -900,6 +923,7 @@
return Qfalse;
}
+
/*
* call-seq:
* File.pipe?(file_name) => true or false
@@ -908,7 +932,7 @@
*/
static VALUE
-test_p(VALUE obj, VALUE fname)
+rb_file_pipe_p(VALUE obj, VALUE fname)
{
#ifdef S_IFIFO
# ifndef S_ISFIFO
@@ -932,7 +956,7 @@
*/
static VALUE
-test_l(VALUE obj, VALUE fname)
+rb_file_symlink_p(VALUE obj, VALUE fname)
{
#ifndef S_ISLNK
# ifdef _S_ISLNK
@@ -968,7 +992,7 @@
*/
static VALUE
-test_S(VALUE obj, VALUE fname)
+rb_file_socket_p(VALUE obj, VALUE fname)
{
#ifndef S_ISSOCK
# ifdef _S_ISSOCK
@@ -1002,7 +1026,7 @@
*/
static VALUE
-test_b(VALUE obj, VALUE fname)
+rb_file_blockdev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISBLK
# ifdef S_IFBLK
@@ -1029,7 +1053,7 @@
* Returns <code>true</code> if the named file is a character device.
*/
static VALUE
-test_c(VALUE obj, VALUE fname)
+rb_file_chardev_p(VALUE obj, VALUE fname)
{
#ifndef S_ISCHR
# define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR)
@@ -1053,7 +1077,7 @@
*/
static VALUE
-test_e(VALUE obj, VALUE fname)
+rb_file_exist_p(VALUE obj, VALUE fname)
{
struct stat st;
@@ -1070,7 +1094,7 @@
*/
static VALUE
-test_r(VALUE obj, VALUE fname)
+rb_file_readable_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
@@ -1087,7 +1111,7 @@
*/
static VALUE
-test_R(VALUE obj, VALUE fname)
+rb_file_readable_real_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
@@ -1118,7 +1142,7 @@
*/
static VALUE
-test_wr(VALUE obj, VALUE fname)
+rb_file_world_readable_p(VALUE obj, VALUE fname)
{
#ifdef S_IROTH
struct stat st;
@@ -1140,7 +1164,7 @@
*/
static VALUE
-test_w(VALUE obj, VALUE fname)
+rb_file_writable_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
@@ -1157,7 +1181,7 @@
*/
static VALUE
-test_W(VALUE obj, VALUE fname)
+rb_file_writable_real_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
@@ -1180,7 +1204,7 @@
*/
static VALUE
-test_ww(VALUE obj, VALUE fname)
+rb_file_world_writable_p(VALUE obj, VALUE fname)
{
#ifdef S_IWOTH
struct stat st;
@@ -1202,7 +1226,7 @@
*/
static VALUE
-test_x(VALUE obj, VALUE fname)
+rb_file_executable_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
@@ -1219,7 +1243,7 @@
*/
static VALUE
-test_X(VALUE obj, VALUE fname)
+rb_file_executable_real_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
@@ -1240,7 +1264,7 @@
*/
static VALUE
-test_f(VALUE obj, VALUE fname)
+rb_file_file_p(VALUE obj, VALUE fname)
{
struct stat st;
@@ -1258,7 +1282,7 @@
*/
static VALUE
-test_z(VALUE obj, VALUE fname)
+rb_file_zero_p(VALUE obj, VALUE fname)
{
struct stat st;
@@ -1276,7 +1300,7 @@
*/
static VALUE
-test_s(VALUE obj, VALUE fname)
+rb_file_size_p(VALUE obj, VALUE fname)
{
struct stat st;
@@ -1295,7 +1319,7 @@
*/
static VALUE
-test_owned(VALUE obj, VALUE fname)
+rb_file_owned_p(VALUE obj, VALUE fname)
{
struct stat st;
@@ -1305,7 +1329,7 @@
}
static VALUE
-test_rowned(VALUE obj, VALUE fname)
+rb_file_rowned_p(VALUE obj, VALUE fname)
{
struct stat st;
@@ -1324,13 +1348,13 @@
*/
static VALUE
-test_grpowned(VALUE obj, VALUE fname)
+rb_file_grpowned_p(VALUE obj, VALUE fname)
{
#ifndef _WIN32
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_gid == getegid()) return Qtrue;
+ if (group_member(st.st_gid)) return Qtrue;
#endif
return Qfalse;
}
@@ -1357,7 +1381,7 @@
*/
static VALUE
-test_suid(VALUE obj, VALUE fname)
+rb_file_suid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISUID
return check3rdbyte(fname, S_ISUID);
@@ -1374,7 +1398,7 @@
*/
static VALUE
-test_sgid(VALUE obj, VALUE fname)
+rb_file_sgid_p(VALUE obj, VALUE fname)
{
#ifdef S_ISGID
return check3rdbyte(fname, S_ISGID);
@@ -1391,7 +1415,7 @@
*/
static VALUE
-test_sticky(VALUE obj, VALUE fname)
+rb_file_sticky_p(VALUE obj, VALUE fname)
{
#ifdef S_ISVTX
return check3rdbyte(fname, S_ISVTX);
@@ -1418,7 +1442,7 @@
*/
static VALUE
-test_identical(VALUE obj, VALUE fname1, VALUE fname2)
+rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
{
#ifndef DOSISH
struct stat st1, st2;
@@ -3262,71 +3286,71 @@
CHECK(1);
switch (cmd) {
case 'b':
- return test_b(0, argv[1]);
+ return rb_file_blockdev_p(0, argv[1]);
case 'c':
- return test_c(0, argv[1]);
+ return rb_file_chardev_p(0, argv[1]);
case 'd':
- return test_d(0, argv[1]);
+ return rb_file_directory_p(0, argv[1]);
case 'a':
case 'e':
- return test_e(0, argv[1]);
+ return rb_file_exist_p(0, argv[1]);
case 'f':
- return test_f(0, argv[1]);
+ return rb_file_file_p(0, argv[1]);
case 'g':
- return test_sgid(0, argv[1]);
+ return rb_file_sgid_p(0, argv[1]);
case 'G':
- return test_grpowned(0, argv[1]);
+ return rb_file_grpowned_p(0, argv[1]);
case 'k':
- return test_sticky(0, argv[1]);
+ return rb_file_sticky_p(0, argv[1]);
case 'l':
- return test_l(0, argv[1]);
+ return rb_file_symlink_p(0, argv[1]);
case 'o':
- return test_owned(0, argv[1]);
+ return rb_file_owned_p(0, argv[1]);
case 'O':
- return test_rowned(0, argv[1]);
+ return rb_file_rowned_p(0, argv[1]);
case 'p':
- return test_p(0, argv[1]);
+ return rb_file_pipe_p(0, argv[1]);
case 'r':
- return test_r(0, argv[1]);
+ return rb_file_readable_p(0, argv[1]);
case 'R':
- return test_R(0, argv[1]);
+ return rb_file_readable_real_p(0, argv[1]);
case 's':
- return test_s(0, argv[1]);
+ return rb_file_size_p(0, argv[1]);
case 'S':
- return test_S(0, argv[1]);
+ return rb_file_socket_p(0, argv[1]);
case 'u':
- return test_suid(0, argv[1]);
+ return rb_file_suid_p(0, argv[1]);
case 'w':
- return test_w(0, argv[1]);
+ return rb_file_writable_p(0, argv[1]);
case 'W':
- return test_W(0, argv[1]);
+ return rb_file_world_writable_p(0, argv[1]);
case 'x':
- return test_x(0, argv[1]);
+ return rb_file_executable_p(0, argv[1]);
case 'X':
- return test_X(0, argv[1]);
+ return rb_file_executable_real_p(0, argv[1]);
case 'z':
- return test_z(0, argv[1]);
+ return rb_file_zero_p(0, argv[1]);
}
}
@@ -3350,7 +3374,7 @@
if (cmd == '-') {
CHECK(2);
- return test_identical(0, argv[1], argv[2]);
+ return rb_file_identical_p(0, argv[1], argv[2]);
}
if (strchr("=<>", cmd)) {
@@ -3651,7 +3675,7 @@
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
- if (get_stat(obj)->st_gid == getegid()) return Qtrue;
+ if (group_member(get_stat(obj)->st_gid)) return Qtrue;
#endif
return Qfalse;
}
@@ -4332,36 +4356,35 @@
rb_mFileTest = rb_define_module("FileTest");
rb_cFile = rb_define_class("File", rb_cIO);
- define_filetest_function("directory?", test_d, 1);
- define_filetest_function("exist?", test_e, 1);
- define_filetest_function("exists?", test_e, 1); /* temporary */
- define_filetest_function("readable?", test_r, 1);
- define_filetest_function("readable_real?", test_R, 1);
- define_filetest_function("world_readable?", test_wr, 1);
- define_filetest_function("writable?", test_w, 1);
- define_filetest_function("writable_real?", test_W, 1);
- define_filetest_function("world_writable?", test_ww, 1);
- define_filetest_function("executable?", test_x, 1);
- define_filetest_function("executable_real?", test_X, 1);
- define_filetest_function("file?", test_f, 1);
- define_filetest_function("zero?", test_z, 1);
- define_filetest_function("size?", test_s, 1);
+ define_filetest_function("directory?", rb_file_directory_p, 1);
+ define_filetest_function("exist?", rb_file_exist_p, 1);
+ define_filetest_function("readable?", rb_file_readable_p, 1);
+ define_filetest_function("readable_real?", rb_file_readable_real_p, 1);
+ define_filetest_function("world_readable?", rb_file_world_writable_p, 1);
+ define_filetest_function("writable?", rb_file_writable_p, 1);
+ define_filetest_function("writable_real?", rb_file_world_writable_p, 1);
+ define_filetest_function("world_writable?", rb_file_world_writable_p, 1);
+ define_filetest_function("executable?", rb_file_executable_p, 1);
+ define_filetest_function("executable_real?", rb_file_executable_real_p, 1);
+ define_filetest_function("file?", rb_file_file_p, 1);
+ define_filetest_function("zero?", rb_file_zero_p, 1);
+ define_filetest_function("size?", rb_file_size_p, 1);
define_filetest_function("size", rb_file_s_size, 1);
- define_filetest_function("owned?", test_owned, 1);
- define_filetest_function("grpowned?", test_grpowned, 1);
+ define_filetest_function("owned?", rb_file_owned_p, 1);
+ define_filetest_function("grpowned?", rb_file_grpowned_p, 1);
- define_filetest_function("pipe?", test_p, 1);
- define_filetest_function("symlink?", test_l, 1);
- define_filetest_function("socket?", test_S, 1);
+ define_filetest_function("pipe?", rb_file_pipe_p, 1);
+ define_filetest_function("symlink?", rb_file_symlink_p, 1);
+ define_filetest_function("socket?", rb_file_socket_p, 1);
- define_filetest_function("blockdev?", test_b, 1);
- define_filetest_function("chardev?", test_c, 1);
+ define_filetest_function("blockdev?", rb_file_blockdev_p, 1);
+ define_filetest_function("chardev?", rb_file_chardev_p, 1);
- define_filetest_function("setuid?", test_suid, 1);
- define_filetest_function("setgid?", test_sgid, 1);
- define_filetest_function("sticky?", test_sticky, 1);
+ define_filetest_function("setuid?", rb_file_suid_p, 1);
+ define_filetest_function("setgid?", rb_file_sgid_p, 1);
+ define_filetest_function("sticky?", rb_file_sticky_p, 1);
- define_filetest_function("identical?", test_identical, 2);
+ define_filetest_function("identical?", rb_file_identical_p, 2);
rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1);
rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
Modified: trunk/instruby.rb
===================================================================
--- trunk/instruby.rb 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/instruby.rb 2006-12-31 08:05:21 UTC (rev 588)
@@ -122,10 +122,10 @@
super(dirs, :mode => 0755) unless dirs.empty?
end
-def install_recursive(src, dest, options = {})
+def install_recursive(srcdir, dest, options = {})
noinst = options.delete(:no_install)
- subpath = src.size..-1
- Dir.glob("#{src}/**/*", File::FNM_DOTMATCH) do |src|
+ subpath = srcdir.size..-1
+ Dir.glob("#{srcdir}/**/*", File::FNM_DOTMATCH) do |src|
next if /\A\.{1,2}\z/ =~ (base = File.basename(src))
next if noinst and File.fnmatch?(noinst, File.basename(src))
d = dest + src[subpath]
Modified: trunk/intern.h
===================================================================
--- trunk/intern.h 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/intern.h 2006-12-31 08:05:21 UTC (rev 588)
@@ -295,6 +295,7 @@
char *rb_path_skip_prefix(const char *);
char *rb_path_last_separator(const char *);
char *rb_path_end(const char *);
+VALUE rb_file_directory_p(VALUE,VALUE);
/* gc.c */
void ruby_set_stack_size(size_t);
NORETURN(void rb_memerror(void));
@@ -564,7 +565,7 @@
void *rb_mod_const_at(VALUE, void*);
void *rb_mod_const_of(VALUE, void*);
VALUE rb_const_list(void*);
-VALUE rb_mod_constants(VALUE);
+VALUE rb_mod_constants(int, VALUE *, VALUE);
VALUE rb_mod_remove_const(VALUE, VALUE);
int rb_const_defined(VALUE, ID);
int rb_const_defined_at(VALUE, ID);
@@ -573,7 +574,6 @@
VALUE rb_const_get_at(VALUE, ID);
VALUE rb_const_get_from(VALUE, ID);
void rb_const_set(VALUE, ID, VALUE);
-VALUE rb_mod_constants(VALUE);
VALUE rb_mod_const_missing(VALUE,VALUE);
VALUE rb_cvar_defined(VALUE, ID);
#define RB_CVAR_SET_4ARGS 1
Modified: trunk/io.c
===================================================================
--- trunk/io.c 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/io.c 2006-12-31 08:05:21 UTC (rev 588)
@@ -1535,17 +1535,21 @@
}
static int
-appendline(OpenFile *fptr, int delim, VALUE *strp)
+appendline(OpenFile *fptr, int delim, VALUE *strp, long *lp)
{
VALUE str = *strp;
int c = EOF;
+ long limit = *lp;
do {
long pending = READ_DATA_PENDING_COUNT(fptr);
if (pending > 0) {
const char *p = READ_DATA_PENDING_PTR(fptr);
- const char *e = memchr(p, delim, pending);
+ const char *e;
long last = 0, len = (c != EOF);
+
+ if (limit > 0 && pending > limit) pending = limit;
+ e = memchr(p, delim, pending);
if (e) pending = e - p + 1;
len += pending;
if (!NIL_P(str)) {
@@ -1560,6 +1564,9 @@
RSTRING_PTR(str)[last++] = c;
}
read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
+ limit -= pending;
+ *lp = limit;
+ if (limit == 0) return RSTRING_PTR(str)[RSTRING_LEN(str)-1];
if (e) return delim;
}
else if (c != EOF) {
@@ -1576,7 +1583,9 @@
rb_thread_wait_fd(fptr->fd);
rb_io_check_closed(fptr);
c = io_getc(fptr);
+ limit--;
if (c < 0) {
+ *lp = limit;
return c;
}
} while (c != delim);
@@ -1624,16 +1633,21 @@
}
static VALUE
-rb_io_getline_fast(OpenFile *fptr, unsigned char delim)
+rb_io_getline_fast(OpenFile *fptr, unsigned char delim, long limit)
{
VALUE str = Qnil;
int c;
- while ((c = appendline(fptr, delim, &str)) != EOF && c != delim);
+ for (;;) {
+ c = appendline(fptr, delim, &str, &limit);
+ if (c == EOF || c == delim || limit == 0) break;
+ }
if (!NIL_P(str)) {
+ if (limit > 0) {
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
+ }
OBJ_TAINT(str);
}
@@ -1649,19 +1663,43 @@
}
static VALUE
-rb_io_getline(VALUE rs, VALUE io)
+rb_io_getline(int argc, VALUE *argv, VALUE io)
{
- VALUE str = Qnil;
+ VALUE rs, lim, str = Qnil;
OpenFile *fptr;
+ long limit;
+ if (argc == 0) {
+ rs = rb_rs;
+ lim = Qnil;
+ }
+ else {
+ rb_scan_args(argc, argv, "11", &rs, &lim);
+ if (NIL_P(lim) && !NIL_P(rs) && TYPE(rs) != T_STRING) {
+ VALUE tmp = rb_check_string_type(rs);
+
+ if (NIL_P(tmp)) {
+ lim = rs;
+ rs = rb_rs;
+ }
+ else {
+ rs = tmp;
+ }
+ }
+ }
+ limit = NIL_P(lim) ? 0 : NUM2LONG(lim);
+
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
if (NIL_P(rs)) {
str = read_all(fptr, 0, Qnil);
if (RSTRING_LEN(str) == 0) return Qnil;
}
+ else if (!NIL_P(lim) && limit == 0) {
+ return rb_str_new(0,0);
+ }
else if (rs == rb_default_rs) {
- return rb_io_getline_fast(fptr, '\n');
+ return rb_io_getline_fast(fptr, '\n', limit);
}
else {
int c, newline;
@@ -1677,20 +1715,21 @@
swallow(fptr, '\n');
}
else if (rslen == 1) {
- return rb_io_getline_fast(fptr, (unsigned char)RSTRING_PTR(rs)[0]);
+ return rb_io_getline_fast(fptr, (unsigned char)RSTRING_PTR(rs)[0], limit);
}
else {
rsptr = RSTRING_PTR(rs);
}
newline = rsptr[rslen - 1];
- while ((c = appendline(fptr, newline, &str)) != EOF) {
+ while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
if (c == newline) {
if (RSTRING_LEN(str) < rslen) continue;
if (!rspara) rscheck(rsptr, rslen, rs);
if (memcmp(RSTRING_PTR(str) + RSTRING_LEN(str) - rslen,
rsptr, rslen) == 0) break;
}
+ if (limit == 0) break;
}
if (rspara) {
@@ -1701,8 +1740,10 @@
}
if (!NIL_P(str)) {
+ if (limit > 0) {
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
+ }
OBJ_TAINT(str);
}
@@ -1716,21 +1757,25 @@
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
- return rb_io_getline_fast(fptr, '\n');
+ return rb_io_getline_fast(fptr, '\n', 0);
}
/*
* call-seq:
- * ios.gets(sep_string=$/) => string or nil
+ * ios.gets(sep=$/) => string or nil
+ * ios.gets(limit) => string or nil
+ * ios.gets(sep, limit) => string or nil
*
* Reads the next ``line'' from the I/O stream; lines are separated by
- * <i>sep_string</i>. A separator of <code>nil</code> reads the entire
+ * <i>sep</i>. A separator of <code>nil</code> reads the entire
* contents, and a zero-length separator reads the input a paragraph at
* a time (two successive newlines in the input separate paragraphs).
* The stream must be opened for reading or an <code>IOError</code>
* will be raised. The line read in will be returned and also assigned
* to <code>$_</code>. Returns <code>nil</code> if called at end of
- * file.
+ * file. If the first argument is an integer, or optional second
+ * argument is given, the returning string would not be longer than the
+ * given value.
*
* File.new("testfile").gets #=> "This is line one\n"
* $_ #=> "This is line one\n"
@@ -1739,16 +1784,9 @@
static VALUE
rb_io_gets_m(int argc, VALUE *argv, VALUE io)
{
- VALUE rs, str;
+ VALUE str;
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- str = rb_io_getline(rs, io);
+ str = rb_io_getline(argc, argv, io);
rb_lastline_set(str);
return str;
@@ -1834,7 +1872,9 @@
/*
* call-seq:
- * ios.readline(sep_string=$/) => string
+ * ios.readline(sep=$/) => string
+ * ios.readline(limit) => string
+ * ios.readline(sep, limit) => string
*
* Reads a line as with <code>IO#gets</code>, but raises an
* <code>EOFError</code> on end of file.
@@ -1853,14 +1893,17 @@
/*
* call-seq:
- * ios.readlines(sep_string=$/) => array
+ * ios.readlines(sep=$/) => array
+ * ios.readlines(limit) => array
+ * ios.readlines(sep, limit) => array
*
* Reads all of the lines in <em>ios</em>, and returns them in
- * <i>anArray</i>. Lines are separated by the optional
- * <i>sep_string</i>. If <i>sep_string</i> is <code>nil</code>, the
- * rest of the stream is returned as a single record.
- * The stream must be opened for reading or an
- * <code>IOError</code> will be raised.
+ * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
+ * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
+ * as a single record. If the first argument is an integer, or
+ * optional second argument is given, the returning string would not be
+ * longer than the given value. The stream must be opened for reading
+ * or an <code>IOError</code> will be raised.
*
* f = File.new("testfile")
* f.readlines[0] #=> "This is line one\n"
@@ -1870,17 +1913,9 @@
rb_io_readlines(int argc, VALUE *argv, VALUE io)
{
VALUE line, ary;
- VALUE rs;
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
ary = rb_ary_new();
- while (!NIL_P(line = rb_io_getline(rs, io))) {
+ while (!NIL_P(line = rb_io_getline(argc, argv, io))) {
rb_ary_push(ary, line);
}
return ary;
@@ -1888,11 +1923,15 @@
/*
* call-seq:
- * ios.each(sep_string=$/) {|line| block } => ios
- * ios.each_line(sep_string=$/) {|line| block } => ios
+ * ios.each(sep=$/) {|line| block } => ios
+ * ios.each(limit) {|line| block } => ios
+ * ios.each(sep,limit) {|line| block } => ios
+ * ios.each_line(sep=$/) {|line| block } => ios
+ * ios.each_line(limit) {|line| block } => ios
+ * ios.each_line(sep,limit) {|line| block } => ios
*
* Executes the block for every line in <em>ios</em>, where lines are
- * separated by <i>sep_string</i>. <em>ios</em> must be opened for
+ * separated by <i>sep</i>. <em>ios</em> must be opened for
* reading or an <code>IOError</code> will be raised.
*
* f = File.new("testfile")
@@ -1910,17 +1949,9 @@
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
VALUE str;
- VALUE rs;
RETURN_ENUMERATOR(io, argc, argv);
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- while (!NIL_P(str = rb_io_getline(rs, io))) {
+ while (!NIL_P(str = rb_io_getline(argc, argv, io))) {
rb_yield(str);
}
return io;
@@ -1963,7 +1994,9 @@
/*
* call-seq:
- * str.lines(separator=$/) => anEnumerator
++ * str.lines(sep=$/) => anEnumerator
++ * str.lines(limit) => anEnumerator
++ * str.lines(sep, limit) => anEnumerator
*
* Returns an enumerator that gives each line in the string.
*
@@ -4371,16 +4404,7 @@
line = rb_io_gets(current_file);
}
else {
- VALUE rs;
-
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- line = rb_io_getline(rs, current_file);
+ line = rb_io_getline(argc, argv, current_file);
}
if (NIL_P(line) && next_p != -1) {
argf_close(current_file);
@@ -4396,18 +4420,22 @@
/*
* call-seq:
- * gets(separator=$/) => string or nil
+ * gets(sep=$/) => string or nil
+ * gets(limit) => string or nil
+ * gets(sep,limit) => string or nil
*
* Returns (and assigns to <code>$_</code>) the next line from the list
- * of files in +ARGV+ (or <code>$*</code>), or from standard
- * input if no files are present on the command line. Returns
- * +nil+ at end of file. The optional argument specifies the
- * record separator. The separator is included with the contents of
- * each record. A separator of +nil+ reads the entire
- * contents, and a zero-length separator reads the input one paragraph
- * at a time, where paragraphs are divided by two consecutive newlines.
- * If multiple filenames are present in +ARGV+,
- * +gets(nil)+ will read the contents one file at a time.
+ * of files in +ARGV+ (or <code>$*</code>), or from standard input if
+ * no files are present on the command line. Returns +nil+ at end of
+ * file. The optional argument specifies the record separator. The
+ * separator is included with the contents of each record. A separator
+ * of +nil+ reads the entire contents, and a zero-length separator
+ * reads the input one paragraph at a time, where paragraphs are
+ * divided by two consecutive newlines. If the first argument is an
+ * integer, or optional second argument is given, the returning string
+ * would not be longer than the given value. If multiple filenames are
+ * present in +ARGV+, +gets(nil)+ will read the contents one file at a
+ * time.
*
* ARGV << "testfile"
* print while gets
@@ -4467,7 +4495,9 @@
/*
* call-seq:
- * readline(separator=$/) => string
+ * readline(sep=$/) => string
+ * readline(limit) => string
+ * readline(sep, limit) => string
*
* Equivalent to <code>Kernel::gets</code>, except
* +readline+ raises +EOFError+ at end of file.
@@ -4503,10 +4533,12 @@
/*
* call-seq:
- * readlines(separator=$/) => array
+ * readlines(sep=$/) => array
+ * readlines(limit) => array
+ * readlines(sep,limit) => array
*
* Returns an array containing the lines returned by calling
- * <code>Kernel.gets(<i>separator</i>)</code> until the end of file.
+ * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
*/
static VALUE
@@ -5079,7 +5111,7 @@
struct foreach_arg {
int argc;
- VALUE sep;
+ VALUE *argv;
VALUE io;
};
@@ -5088,7 +5120,7 @@
{
VALUE str;
- while (!NIL_P(str = rb_io_getline(arg->sep, arg->io))) {
+ while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
rb_yield(str);
}
return Qnil;
@@ -5096,10 +5128,12 @@
/*
* call-seq:
- * IO.foreach(name, sep_string=$/) {|line| block } => nil
+ * IO.foreach(name, sep=$/) {|line| block } => nil
+ * IO.foreach(name, limit) {|line| block } => nil
+ * IO.foreach(name, sep, limit) {|line| block } => nil
*
* Executes the block for every line in the named I/O port, where lines
- * are separated by <em>sep_string</em>.
+ * are separated by <em>sep</em>.
*
* IO.foreach("testfile") {|x| print "GOT ", x }
*
@@ -5118,33 +5152,30 @@
struct foreach_arg arg;
RETURN_ENUMERATOR(self, argc, argv);
- rb_scan_args(argc, argv, "11", &fname, &arg.sep);
+ rb_scan_args(argc, argv, "12", &fname, NULL, NULL);
FilePathValue(fname);
- if (argc == 1) {
- arg.sep = rb_default_rs;
- }
- else if (!NIL_P(arg.sep)) {
- StringValue(arg.sep);
- }
arg.io = rb_io_open(RSTRING_PTR(fname), "r");
if (NIL_P(arg.io)) return Qnil;
-
+ arg.argc = argc - 1;
+ arg.argv = argv + 1;
return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
}
static VALUE
io_s_readlines(struct foreach_arg *arg)
{
- return rb_io_readlines(arg->argc, &arg->sep, arg->io);
+ return rb_io_readlines(arg->argc, arg->argv, arg->io);
}
/*
* call-seq:
- * IO.readlines(name, sep_string=$/) => array
+ * IO.readlines(name, sep=$/) => array
+ * IO.readlines(name, limit) => array
+ * IO.readlines(name, sep, limit) => array
*
* Reads the entire file specified by <i>name</i> as individual
* lines, and returns those lines in an array. Lines are separated by
- * <i>sep_string</i>.
+ * <i>sep</i>.
*
* a = IO.readlines("testfile")
* a[0] #=> "This is line one\n"
@@ -5157,18 +5188,19 @@
VALUE fname;
struct foreach_arg arg;
- rb_scan_args(argc, argv, "11", &fname, &arg.sep);
+ rb_scan_args(argc, argv, "12", &fname, NULL, NULL);
FilePathValue(fname);
- arg.argc = argc - 1;
arg.io = rb_io_open(RSTRING_PTR(fname), "r");
if (NIL_P(arg.io)) return Qnil;
+ arg.argc = argc - 1;
+ arg.argv = argv + 1;
return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
}
static VALUE
io_s_read(struct foreach_arg *arg)
{
- return io_read(arg->argc, &arg->sep, arg->io);
+ return io_read(arg->argc, arg->argv, arg->io);
}
/*
@@ -5190,9 +5222,10 @@
VALUE fname, offset;
struct foreach_arg arg;
- rb_scan_args(argc, argv, "12", &fname, &arg.sep, &offset);
+ rb_scan_args(argc, argv, "12", &fname, NULL, &offset);
FilePathValue(fname);
- arg.argc = argc ? 1 : 0;
+ arg.argc = argc > 1 ? 1 : 0;
+ arg.argv = argv + 1;
arg.io = rb_io_open(RSTRING_PTR(fname), "r");
if (NIL_P(arg.io)) return Qnil;
if (!NIL_P(offset)) {
@@ -5278,7 +5311,7 @@
VALUE tmp, str, length;
long len = 0;
- rb_scan_args(argc, argv, "02", &length, &str);
+ rb_scan_args(argc, argv, "11", &length, &str);
if (!NIL_P(length)) {
len = NUM2LONG(argv[0]);
}
Modified: trunk/lib/README
===================================================================
--- trunk/lib/README 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/lib/README 2006-12-31 08:05:21 UTC (rev 588)
@@ -10,7 +10,6 @@
csv.rb CSV parser/generator
date.rb date object
date/format.rb date parsing and formatting
-date2.rb date object (obsolete; use date)
debug.rb ruby debugger
delegate.rb delegates messages to other object
drb.rb distributed Ruby
Modified: trunk/lib/date/format.rb
===================================================================
--- trunk/lib/date/format.rb 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/lib/date/format.rb 2006-12-31 08:05:21 UTC (rev 588)
@@ -1,1086 +1,1061 @@
-# format.rb: Written by Tadayoshi Funaba 1999-2006
-# $Id: format.rb,v 2.28 2006-10-25 06:45:12+09 tadf Exp $
-
-require 'rational'
-
-class Date
-
- module Format # :nodoc:
-
- MONTHS = {
- 'january' => 1, 'february' => 2, 'march' => 3, 'april' => 4,
- 'may' => 5, 'june' => 6, 'july' => 7, 'august' => 8,
- 'september'=> 9, 'october' =>10, 'november' =>11, 'december' =>12
- }
-
- DAYS = {
- 'sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday'=> 3,
- 'thursday' => 4, 'friday' => 5, 'saturday' => 6
- }
-
- ABBR_MONTHS = {
- 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4,
- 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8,
- 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12
- }
-
- ABBR_DAYS = {
- 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
- 'thu' => 4, 'fri' => 5, 'sat' => 6
- }
-
- ZONES = {
- 'ut' => 0*3600, 'gmt' => 0*3600, 'est' => -5*3600, 'edt' => -4*3600,
- 'cst' => -6*3600, 'cdt' => -5*3600, 'mst' => -7*3600, 'mdt' => -6*3600,
- 'pst' => -8*3600, 'pdt' => -7*3600,
- 'a' => 1*3600, 'b' => 2*3600, 'c' => 3*3600, 'd' => 4*3600,
- 'e' => 5*3600, 'f' => 6*3600, 'g' => 7*3600, 'h' => 8*3600,
- 'i' => 9*3600, 'k' => 10*3600, 'l' => 11*3600, 'm' => 12*3600,
- 'n' => -1*3600, 'o' => -2*3600, 'p' => -3*3600, 'q' => -4*3600,
- 'r' => -5*3600, 's' => -6*3600, 't' => -7*3600, 'u' => -8*3600,
- 'v' => -9*3600, 'w' =>-10*3600, 'x' =>-11*3600, 'y' =>-12*3600,
- 'z' => 0*3600,
- 'utc' => 0*3600, 'wet' => 0*3600, 'bst' => 1*3600, 'wat' => -1*3600,
- 'at' => -2*3600, 'ast' => -4*3600, 'adt' => -3*3600, 'yst' => -9*3600,
- 'ydt' => -8*3600, 'hst' =>-10*3600, 'hdt' => -9*3600, 'cat' =>-10*3600,
- 'ahst'=>-10*3600, 'nt' =>-11*3600, 'idlw'=>-12*3600, 'cet' => 1*3600,
- 'met' => 1*3600, 'mewt'=> 1*3600, 'mest'=> 2*3600, 'mesz'=> 2*3600,
- 'swt' => 1*3600, 'sst' => 2*3600, 'fwt' => 1*3600, 'fst' => 2*3600,
- 'eet' => 2*3600, 'bt' => 3*3600, 'zp4' => 4*3600, 'zp5' => 5*3600,
- 'zp6' => 6*3600, 'wast'=> 7*3600, 'wadt'=> 8*3600, 'cct' => 8*3600,
- 'jst' => 9*3600, 'east'=> 10*3600, 'eadt'=> 11*3600, 'gst' => 10*3600,
- 'nzt' => 12*3600, 'nzst'=> 12*3600, 'nzdt'=> 13*3600, 'idle'=> 12*3600,
-
- 'afghanistan' => 16200, 'alaskan' => -32400,
- 'arab' => 10800, 'arabian' => 14400,
- 'arabic' => 10800, 'atlantic' => -14400,
- 'aus central' => 34200, 'aus eastern' => 36000,
- 'azores' => -3600, 'canada central' => -21600,
- 'cape verde' => -3600, 'caucasus' => 14400,
- 'cen. australia' => 34200, 'central america' => -21600,
- 'central asia' => 21600, 'central europe' => 3600,
- 'central european' => 3600, 'central pacific' => 39600,
- 'central' => -21600, 'china' => 28800,
- 'dateline' => -43200, 'e. africa' => 10800,
- 'e. australia' => 36000, 'e. europe' => 7200,
- 'e. south america' => -10800, 'eastern' => -18000,
- 'egypt' => 7200, 'ekaterinburg' => 18000,
- 'fiji' => 43200, 'fle' => 7200,
- 'greenland' => -10800, 'greenwich' => 0,
- 'gtb' => 7200, 'hawaiian' => -36000,
- 'india' => 19800, 'iran' => 12600,
- 'jerusalem' => 7200, 'korea' => 32400,
- 'mexico' => -21600, 'mid-atlantic' => -7200,
- 'mountain' => -25200, 'myanmar' => 23400,
- 'n. central asia' => 21600, 'nepal' => 20700,
- 'new zealand' => 43200, 'newfoundland' => -12600,
- 'north asia east' => 28800, 'north asia' => 25200,
- 'pacific sa' => -14400, 'pacific' => -28800,
- 'romance' => 3600, 'russian' => 10800,
- 'sa eastern' => -10800, 'sa pacific' => -18000,
- 'sa western' => -14400, 'samoa' => -39600,
- 'se asia' => 25200, 'malay peninsula' => 28800,
- 'south africa' => 7200, 'sri lanka' => 21600,
- 'taipei' => 28800, 'tasmania' => 36000,
- 'tokyo' => 32400, 'tonga' => 46800,
- 'us eastern' => -18000, 'us mountain' => -25200,
- 'vladivostok' => 36000, 'w. australia' => 28800,
- 'w. central africa' => 3600, 'w. europe' => 3600,
- 'west asia' => 18000, 'west pacific' => 36000,
- 'yakutsk' => 32400
- }
-
- [MONTHS, DAYS, ABBR_MONTHS, ABBR_DAYS, ZONES].each do |x|
- x.freeze
- end
-
- class Bag # :nodoc:
-
- def method_missing(t, *args, &block)
- t = t.to_s
- set = t.chomp!('=')
- t = '@' + t
- if set
- instance_variable_set(t, *args)
- else
- if instance_variables.include?(t)
- instance_variable_get(t)
- end
- end
- end
-
- def to_hash
- instance_variables.
- select{|n| !instance_variable_get(n).nil?}.grep(/\A@[^_]/).
- inject({}){|r, n| r[n[1..-1].intern] = instance_variable_get(n); r}
- end
-
- end
-
- end
-
- def emit(e, f) # :nodoc:
- case e
- when Numeric
- sign = %w(+ + -)[e <=> 0]
- e = e.abs
- end
-
- s = e.to_s
-
- if f[:s] && f[:p] == '0'
- f[:w] -= 1
- end
-
- if f[:s] && f[:p] == "\s"
- s[0,0] = sign
- end
-
- if f[:p] != '-'
- s = s.rjust(f[:w], f[:p])
- end
-
- if f[:s] && f[:p] != "\s"
- s[0,0] = sign
- end
-
- s = s.upcase if f[:u]
- s = s.downcase if f[:d]
- s
- end
-
- def emit_w(e, w, f) # :nodoc:
- f[:w] = [f[:w], w].compact.max
- emit(e, f)
- end
-
- def emit_n(e, w, f) # :nodoc:
- f[:p] ||= '0'
- emit_w(e, w, f)
- end
-
- def emit_sn(e, w, f) # :nodoc:
- if e < 0
- w += 1
- f[:s] = true
- end
- emit_n(e, w, f)
- end
-
- def emit_z(e, w, f) # :nodoc:
- w += 1
- f[:s] = true
- emit_n(e, w, f)
- end
-
- def emit_a(e, w, f) # :nodoc:
- f[:p] ||= "\s"
- emit_w(e, w, f)
- end
-
- def emit_ad(e, w, f) # :nodoc:
- if f[:x]
- f[:u] = true
- f[:d] = false
- end
- emit_a(e, w, f)
- end
-
- def emit_au(e, w, f) # :nodoc:
- if f[:x]
- f[:u] = false
- f[:d] = true
- end
- emit_a(e, w, f)
- end
-
- private :emit, :emit_w, :emit_n, :emit_sn, :emit_z,
- :emit_a, :emit_ad, :emit_au
-
- def strftime(fmt='%F')
- fmt.gsub(/%([-_0^#]+)?(\d+)?[EO]?(:{1,3}z|.)/m) do |m|
- f = {}
- s, w, c = $1, $2, $3
- if s
- s.scan(/./) do |k|
- case k
- when '-'; f[:p] = '-'
- when '_'; f[:p] = "\s"
- when '0'; f[:p] = '0'
- when '^'; f[:u] = true
- when '#'; f[:x] = true
- end
- end
- end
- if w
- f[:w] = w.to_i
- end
- case c
- when 'A'; emit_ad(DAYNAMES[wday], 0, f)
- when 'a'; emit_ad(ABBR_DAYNAMES[wday], 0, f)
- when 'B'; emit_ad(MONTHNAMES[mon], 0, f)
- when 'b'; emit_ad(ABBR_MONTHNAMES[mon], 0, f)
- when 'C'; emit_sn((year / 100).floor, 2, f)
- when 'c'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 0, f)
- when 'D'; emit_a(strftime('%m/%d/%y'), 0, f)
- when 'd'; emit_n(mday, 2, f)
- when 'e'; emit_a(mday, 2, f)
- when 'F'
- if m == '%F'
- format('%.4d-%02d-%02d', year, mon, mday) # 4p
- else
- emit_a(strftime('%Y-%m-%d'), 0, f)
- end
- when 'G'; emit_sn(cwyear, 4, f)
- when 'g'; emit_n(cwyear % 100, 2, f)
- when 'H'; emit_n(hour, 2, f)
- when 'h'; emit_ad(strftime('%b'), 0, f)
- when 'I'; emit_n((hour % 12).nonzero? || 12, 2, f)
- when 'j'; emit_n(yday, 3, f)
- when 'k'; emit_a(hour, 2, f)
- when 'L'
- emit_n((sec_fraction / (1.to_r/86400/(10**3))).round, 3, f)
- when 'l'; emit_a((hour % 12).nonzero? || 12, 2, f)
- when 'M'; emit_n(min, 2, f)
- when 'm'; emit_n(mon, 2, f)
- when 'N'
- emit_n((sec_fraction / (1.to_r/86400/(10**9))).round, 9, f)
- when 'n'; "\n"
- when 'P'; emit_ad(strftime('%p').downcase, 0, f)
- when 'p'; emit_au(if hour < 12 then 'AM' else 'PM' end, 0, f)
- when 'Q'
- d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0)
- s = (d * 86400*10**3).to_i
- emit_sn(s, 1, f)
- when 'R'; emit_a(strftime('%H:%M'), 0, f)
- when 'r'; emit_a(strftime('%I:%M:%S %p'), 0, f)
- when 'S'; emit_n(sec, 2, f)
- when 's'
- d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0)
- s = (d * 86400).to_i
- emit_sn(s, 1, f)
- when 'T'
- if m == '%T'
- format('%02d:%02d:%02d', hour, min, sec) # 4p
- else
- emit_a(strftime('%H:%M:%S'), 0, f)
- end
- when 't'; "\t"
- when 'U', 'W'
- emit_n(if c == 'U' then wnum0 else wnum1 end, 2, f)
- when 'u'; emit_n(cwday, 1, f)
- when 'V'; emit_n(cweek, 2, f)
- when 'v'; emit_a(strftime('%e-%b-%Y'), 0, f)
- when 'w'; emit_n(wday, 1, f)
- when 'X'; emit_a(strftime('%H:%M:%S'), 0, f)
- when 'x'; emit_a(strftime('%m/%d/%y'), 0, f)
- when 'Y'; emit_sn(year, 4, f)
- when 'y'; emit_n(year % 100, 2, f)
- when 'Z'; emit_au(strftime('%:z'), 0, f)
- when /\A(:{0,3})z/
- t = $1.size
- sign = if offset < 0 then -1 else +1 end
- fr = offset.abs
- hh, fr = fr.divmod(1.to_r/24)
- mm, fr = fr.divmod(1.to_r/1440)
- ss, fr = fr.divmod(1.to_r/86400)
- if t == 3
- if ss.nonzero? then t = 2
- elsif mm.nonzero? then t = 1
- else t = -1
- end
- end
- case t
- when -1
- tail = []
- sep = ''
- when 0
- f[:w] -= 2 if f[:w]
- tail = ['%02d' % mm]
- sep = ''
- when 1
- f[:w] -= 3 if f[:w]
- tail = ['%02d' % mm]
- sep = ':'
- when 2
- f[:w] -= 6 if f[:w]
- tail = ['%02d' % mm, '%02d' % ss]
- sep = ':'
- end
- ([emit_z(sign * hh, 2, f)] + tail).join(sep)
- when '%'; emit_a('%', 0, f)
- when '+'; emit_a(strftime('%a %b %e %H:%M:%S %Z %Y'), 0, f)
- when '1'
- if $VERBOSE
- warn("warning: strftime: %1 is deprecated; forget this")
- end
- emit_n(jd, 1, f)
- when '2'
- if $VERBOSE
- warn("warning: strftime: %2 is deprecated; use '%Y-%j'")
- end
- emit_a(strftime('%Y-%j'), 0, f)
- when '3'
- if $VERBOSE
- warn("warning: strftime: %3 is deprecated; use '%F'")
- end
- emit_a(strftime('%F'), 0, f)
- else
- c
- end
- end
- end
-
-# alias_method :format, :strftime
-
- def asctime() strftime('%c') end
-
- alias_method :ctime, :asctime
-
-=begin
- def iso8601() strftime('%F') end
-
- def rfc3339() iso8601 end
-
- def rfc2822() strftime('%a, %-d %b %Y %T %z') end
-
- alias_method :rfc822, :rfc2822
-
- def jisx0301
- if jd < 2405160
- iso8601
- else
- case jd
- when 2405160...2419614
- g = 'M%02d' % (year - 1867)
- when 2419614...2424875
- g = 'T%02d' % (year - 1911)
- when 2424875...2447535
- g = 'S%02d' % (year - 1925)
- else
- g = 'H%02d' % (year - 1988)
- end
- g + strftime('.%m.%d')
- end
- end
-
- def beat(n=0)
- i, f = (new_offset(1.to_r/24).day_fraction * 1000).divmod(1)
- ('@%03d' % i) +
- if n < 1
- ''
- else
- '.%0*d' % [n, (f / (1.to_r/(10**n))).round]
- end
- end
-=end
-
- def self.num_pattern? (s) # :nodoc:
- /\A%[EO]?[CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy\d]/ =~ s || /\A\d/ =~ s
- end
-
- private_class_method :num_pattern?
-
- def self._strptime_i(str, fmt, e) # :nodoc:
- fmt.scan(/%[EO]?(:{1,3}z|.)|(.)/m) do |s, c|
- if s
- case s
- when 'A', 'a'
- return unless str.sub!(/\A(#{Format::DAYS.keys.join('|')})/io, '') ||
- str.sub!(/\A(#{Format::ABBR_DAYS.keys.join('|')})/io, '')
- val = Format::DAYS[$1.downcase] || Format::ABBR_DAYS[$1.downcase]
- return unless val
- e.wday = val
- when 'B', 'b', 'h'
- return unless str.sub!(/\A(#{Format::MONTHS.keys.join('|')})/io, '') ||
- str.sub!(/\A(#{Format::ABBR_MONTHS.keys.join('|')})/io, '')
- val = Format::MONTHS[$1.downcase] || Format::ABBR_MONTHS[$1.downcase]
- return unless val
- e.mon = val
- when 'C'
- return unless str.sub!(if num_pattern?($')
- then /\A([-+]?\d{1,2})/
- else /\A([-+]?\d{1,})/
- end, '')
- val = $1.to_i
- e._cent = val
- when 'c'
- return unless _strptime_i(str, '%a %b %e %H:%M:%S %Y', e)
- when 'D'
- return unless _strptime_i(str, '%m/%d/%y', e)
- when 'd', 'e'
- return unless str.sub!(/\A( \d|\d{1,2})/, '')
- val = $1.to_i
- return unless (1..31) === val
- e.mday = val
- when 'F'
- return unless _strptime_i(str, '%Y-%m-%d', e)
- when 'G'
- return unless str.sub!(if num_pattern?($')
- then /\A([-+]?\d{1,4})/
- else /\A([-+]?\d{1,})/
- end, '')
- val = $1.to_i
- e.cwyear = val
- when 'g'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (0..99) === val
- e.cwyear = val
- e._cent ||= if val >= 69 then 19 else 20 end
- when 'H', 'k'
- return unless str.sub!(/\A( \d|\d{1,2})/, '')
- val = $1.to_i
- return unless (0..24) === val
- e.hour = val
- when 'I', 'l'
- return unless str.sub!(/\A( \d|\d{1,2})/, '')
- val = $1.to_i
- return unless (1..12) === val
- e.hour = val
- when 'j'
- return unless str.sub!(/\A(\d{1,3})/, '')
- val = $1.to_i
- return unless (1..366) === val
- e.yday = val
- when 'L'
- return unless str.sub!(if num_pattern?($')
- then /\A([-+]?\d{1,3})/
- else /\A([-+]?\d{1,})/
- end, '')
-# val = $1.to_i.to_r / (10**3)
- val = $1.to_i.to_r / (10**$1.size)
- e.sec_fraction = val
- when 'M'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (0..59) === val
- e.min = val
- when 'm'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (1..12) === val
- e.mon = val
- when 'N'
- return unless str.sub!(if num_pattern?($')
- then /\A([-+]?\d{1,9})/
- else /\A([-+]?\d{1,})/
- end, '')
-# val = $1.to_i.to_r / (10**9)
- val = $1.to_i.to_r / (10**$1.size)
- e.sec_fraction = val
- when 'n', 't'
- return unless _strptime_i(str, "\s", e)
- when 'P', 'p'
- return unless str.sub!(/\A([ap])(?:m\b|\.m\.)/i, '')
- e._merid = if $1.downcase == 'a' then 0 else 12 end
- when 'Q'
- return unless str.sub!(/\A(-?\d{1,})/, '')
- val = $1.to_i.to_r / 10**3
- e.seconds = val
- when 'R'
- return unless _strptime_i(str, '%H:%M', e)
- when 'r'
- return unless _strptime_i(str, '%I:%M:%S %p', e)
- when 'S'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (0..60) === val
- e.sec = val
- when 's'
- return unless str.sub!(/\A(-?\d{1,})/, '')
- val = $1.to_i
- e.seconds = val
- when 'T'
- return unless _strptime_i(str, '%H:%M:%S', e)
- when 'U', 'W'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (0..53) === val
- e.__send__(if s == 'U' then :wnum0= else :wnum1= end, val)
- when 'u'
- return unless str.sub!(/\A(\d{1})/, '')
- val = $1.to_i
- return unless (1..7) === val
- e.cwday = val
- when 'V'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (1..53) === val
- e.cweek = val
- when 'v'
- return unless _strptime_i(str, '%e-%b-%Y', e)
- when 'w'
- return unless str.sub!(/\A(\d{1})/, '')
- val = $1.to_i
- return unless (0..6) === val
- e.wday = val
- when 'X'
- return unless _strptime_i(str, '%H:%M:%S', e)
- when 'x'
- return unless _strptime_i(str, '%m/%d/%y', e)
- when 'Y'
- return unless str.sub!(if num_pattern?($')
- then /\A([-+]?\d{1,4})/
- else /\A([-+]?\d{1,})/
- end, '')
- val = $1.to_i
- e.year = val
- when 'y'
- return unless str.sub!(/\A(\d{1,2})/, '')
- val = $1.to_i
- return unless (0..99) === val
- e.year = val
- e._cent ||= if val >= 69 then 19 else 20 end
- when 'Z', /\A:{0,3}z/
- return unless str.sub!(/\A((?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
- |[a-z.\s]+(?:standard|daylight)\s+time\b
- |[a-z]+(?:\s+dst)?\b
- )/ix, '')
- val = $1
- e.zone = val
- offset = zone_to_diff(val)
- e.offset = offset
- when '%'
- return unless str.sub!(/\A%/, '')
- when '+'
- return unless _strptime_i(str, '%a %b %e %H:%M:%S %Z %Y', e)
- when '1'
- if $VERBOSE
- warn("warning: strptime: %1 is deprecated; forget this")
- end
- return unless str.sub!(/\A(\d+)/, '')
- val = $1.to_i
- e.jd = val
- when '2'
- if $VERBOSE
- warn("warning: strptime: %2 is deprecated; use '%Y-%j'")
- end
- return unless _strptime_i(str, '%Y-%j', e)
- when '3'
- if $VERBOSE
- warn("warning: strptime: %3 is deprecated; use '%F'")
- end
- return unless _strptime_i(str, '%F', e)
- else
- return unless str.sub!(Regexp.new('\\A' + Regexp.quote(s)), '')
- end
- else
- case c
- when /\A[\s\v]/
- str.sub!(/\A[\s\v]+/, '')
- else
- return unless str.sub!(Regexp.new('\\A' + Regexp.quote(c)), '')
- end
- end
- end
- end
-
- private_class_method :_strptime_i
-
- def self._strptime(str, fmt='%F')
- e = Format::Bag.new
- return unless _strptime_i(str.dup, fmt, e)
-
- if e._cent
- if e.cwyear
- e.cwyear += e._cent * 100
- end
- if e.year
- e. year += e._cent * 100
- end
- end
-
- if e._merid
- if e.hour
- e.hour %= 12
- e.hour += e._merid
- end
- end
-
- e.to_hash
- end
-
- def self.s3e(e, y, m, d, bc=false)
- unless String === m
- m = m.to_s
- end
-
- if y == nil
- if d && d.size > 2
- y = d
- d = nil
- end
- if d && d[0,1] == "'"
- y = d
- d = nil
- end
- end
-
- if y
- y.scan(/(\d+)(.+)?/)
- if $2
- y, d = d, $1
- end
- end
-
- if m
- if m[0,1] == "'" || m.size > 2
- y, m, d = m, d, y # us -> be
- end
- end
-
- if d
- if d[0,1] == "'" || d.size > 2
- y, d = d, y
- end
- end
-
- if y
- y =~ /([-+])?(\d+)/
- if $1 || $2.size > 2
- c = false
- end
- iy = $&.to_i
- if bc
- iy = -iy + 1
- end
- e.year = iy
- end
-
- if m
- m =~ /\d+/
- e.mon = $&.to_i
- end
-
- if d
- d =~ /\d+/
- e.mday = $&.to_i
- end
-
- if c != nil
- e._comp = c
- end
-
- end
-
- private_class_method :s3e
-
- def self._parse_day(str, e) # :nodoc:
- if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/ino, ' ')
- e.wday = Format::ABBR_DAYS[$1.downcase]
- true
-=begin
- elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/in, ' ')
- e.wday = %w(su mo tu we th fr sa).index($1.downcase)
- true
-=end
- end
- end
-
- def self._parse_time(str, e) # :nodoc:
- if str.sub!(
- /(
- (?:
- \d+\s*:\s*\d+
- (?:
- \s*:\s*\d+(?:[,.]\d*)?
- )?
- |
- \d+\s*h(?:\s*\d+m?(?:\s*\d+s?)?)?
- )
- (?:
- \s*
- [ap](?:m\b|\.m\.)
- )?
- |
- \d+\s*[ap](?:m\b|\.m\.)
- )
- (?:
- \s*
- (
- (?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
- |
- [a-z.\s]+(?:standard|daylight)\stime\b
- |
- [a-z]+(?:\sdst)?\b
- )
- )?
- /inx,
- ' ')
-
- t = $1
- e.zone = $2 if $2
-
- t =~ /\A(\d+)h?
- (?:\s*:?\s*(\d+)m?
- (?:
- \s*:?\s*(\d+)(?:[,.](\d+))?s?
- )?
- )?
- (?:\s*([ap])(?:m\b|\.m\.))?/inx
-
- e.hour = $1.to_i
- e.min = $2.to_i if $2
- e.sec = $3.to_i if $3
- e.sec_fraction = $4.to_i.to_r / (10**$4.size) if $4
-
- if $5
- e.hour %= 12
- if $5.downcase == 'p'
- e.hour += 12
- end
- end
- true
- end
- end
-
- def self._parse_beat(str, e) # :nodoc:
- if str.sub!(/ \s*(\d+)(?:[,.](\d*))?/, ' ')
- beat = $1.to_i.to_r
- beat += $2.to_i.to_r / (10**$2.size) if $2
- secs = beat.to_r / 1000
- h, min, s, fr = self.day_fraction_to_time(secs)
- e.hour = h
- e.min = min
- e.sec = s
- e.sec_fraction = fr * 86400
- e.zone = '+01:00'
- true
- end
- end
-
- def self._parse_eu(str, e) # :nodoc:
- if str.sub!(
- /'?(\d+)[^-\d\s]*
- \s*
- (#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
- (?:
- \s*
- (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
- \s*
- ('?-?\d+(?:(?:st|nd|rd|th)\b)?)
- )?
- /inox,
- ' ') # '
- s3e(e, $4, Format::ABBR_MONTHS[$2.downcase], $1,
- $3 && $3[0,1].downcase == 'b')
- true
- end
- end
-
- def self._parse_us(str, e) # :nodoc:
- if str.sub!(
- /\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
- \s*
- ('?\d+)[^-\d\s']*
- (?:
- \s*
- (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
- \s*
- ('?-?\d+)
- )?
- /inox,
- ' ') # '
- s3e(e, $4, Format::ABBR_MONTHS[$1.downcase], $2,
- $3 && $3[0,1].downcase == 'b')
- true
- end
- end
-
- def self._parse_iso(str, e) # :nodoc:
- if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)/n, ' ')
- s3e(e, $1, $2, $3)
- true
- end
- end
-
- def self._parse_iso2(str, e) # :nodoc:
- if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d+))?/in, ' ')
- e.cwyear = $1.to_i if $1
- e.cweek = $2.to_i
- e.cwday = $3.to_i if $3
- true
- elsif str.sub!(/--(\d{2})-(\d{2})\b/n, ' ')
- e.mon = $1.to_i
- e.mday = $2.to_i
- true
- elsif str.sub!(/\b(\d{2}|\d{4})-(\d{2,3})\b/n, ' ')
- e.year = $1.to_i
- if $2.size < 3
- e.mon = $2.to_i
- else
- e.yday = $2.to_i
- end
- true
- end
- end
-
- def self._parse_jis(str, e) # :nodoc:
- if str.sub!(/\b([MTSH])(\d+)\.(\d+)\.(\d+)/in, ' ')
- era = { 'm'=>1867,
- 't'=>1911,
- 's'=>1925,
- 'h'=>1988
- }[$1.downcase]
- e.year = $2.to_i + era
- e.mon = $3.to_i
- e.mday = $4.to_i
- true
- end
- end
-
- def self._parse_vms(str, e) # :nodoc:
- if str.sub!(/('?-?\d+)-(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
- -('?-?\d+)/inox, ' ')
- s3e(e, $3, Format::ABBR_MONTHS[$2.downcase], $1)
- true
- elsif str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
- -('?-?\d+)(?:-('?-?\d+))?/inox, ' ')
- s3e(e, $3, Format::ABBR_MONTHS[$1.downcase], $2)
- true
- end
- end
-
- def self._parse_sla_ja(str, e) # :nodoc:
- if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
- s3e(e, $1, $2, $3)
- true
- end
- end
-
- def self._parse_sla_eu(str, e) # :nodoc:
- if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
- s3e(e, $3, $2, $1)
- true
- end
- end
-
- def self._parse_sla_us(str, e) # :nodoc:
- if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
- s3e(e, $3, $1, $2)
- true
- end
- end
-
- def self._parse_year(str, e) # :nodoc:
- if str.sub!(/'(\d+)\b/in, ' ')
- e.year = $1.to_i
- true
- end
- end
-
- def self._parse_mon(str, e) # :nodoc:
- if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/ino, ' ')
- e.mon = Format::ABBR_MONTHS[$1.downcase]
- true
- end
- end
-
- def self._parse_mday(str, e) # :nodoc:
- if str.sub!(/(\d+)(st|nd|rd|th)\b/in, ' ')
- e.mday = $1.to_i
- true
- end
- end
-
- def self._parse_ddd(str, e) # :nodoc:
- if str.sub!(
- /([-+]?)(\d{2,14})
- (?:
- \s*
- T?
- \s*
- (\d{2,6})(?:[,.](\d*))?
- )?
- (?:
- \s*
- (
- Z
- |
- [-+]\d{1,4}
- )
- \b
- )?
- /inx,
- ' ')
- case $2.size
- when 2
- e.mday = $2[ 0, 2].to_i
- when 4
- e.mon = $2[ 0, 2].to_i
- e.mday = $2[ 2, 2].to_i
- when 6
- e.year = ($1 + $2[ 0, 2]).to_i
- e.mon = $2[ 2, 2].to_i
- e.mday = $2[ 4, 2].to_i
- when 8, 10, 12, 14
- e.year = ($1 + $2[ 0, 4]).to_i
- e.mon = $2[ 4, 2].to_i
- e.mday = $2[ 6, 2].to_i
- e.hour = $2[ 8, 2].to_i if $2.size >= 10
- e.min = $2[10, 2].to_i if $2.size >= 12
- e.sec = $2[12, 2].to_i if $2.size >= 14
- e._comp = false
- when 3
- e.yday = $2[ 0, 3].to_i
- when 5
- e.year = ($1 + $2[ 0, 2]).to_i
- e.yday = $2[ 2, 3].to_i
- when 7
- e.year = ($1 + $2[ 0, 4]).to_i
- e.yday = $2[ 4, 3].to_i
- end
- if $3
- case $3.size
- when 2, 4, 6
- e.hour = $3[ 0, 2].to_i
- e.min = $3[ 2, 2].to_i if $3.size >= 4
- e.sec = $3[ 4, 2].to_i if $3.size >= 6
- end
- end
- if $4
- e.sec_fraction = $4.to_i.to_r / (10**$4.size)
- end
- if $5
- e.zone = $5
- end
- true
- end
- end
-
- private_class_method :_parse_day, :_parse_time, :_parse_beat,
- :_parse_eu, :_parse_us, :_parse_iso, :_parse_iso2,
- :_parse_jis, :_parse_vms,
- :_parse_sla_ja, :_parse_sla_eu, :_parse_sla_us,
- :_parse_year, :_parse_mon, :_parse_mday, :_parse_ddd
-
- def self._parse(str, comp=false)
- str = str.dup
-
- e = Format::Bag.new
-
- e._comp = comp
-
- str.gsub!(/[^-+',.\/:0-9@a-z\x80-\xff]+/in, ' ')
-
- _parse_time(str, e) # || _parse_beat(str, e)
- _parse_day(str, e)
-
- _parse_eu(str, e) ||
- _parse_us(str, e) ||
- _parse_iso(str, e) ||
- _parse_jis(str, e) ||
- _parse_vms(str, e) ||
- _parse_sla_us(str, e) ||
- _parse_iso2(str, e) ||
- _parse_year(str, e) ||
- _parse_mon(str, e) ||
- _parse_mday(str, e) ||
- _parse_ddd(str, e)
-
- if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/in, ' ')
- if e.year
- e.year = -e.year + 1
- end
- end
-
- if str.sub!(/\A\s*(\d{1,2})\s*\z/n, ' ')
- if e.hour && !e.mday
- v = $1.to_i
- if (1..31) === v
- e.mday = v
- end
- end
- if e.mday && !e.hour
- v = $1.to_i
- if (0..24) === v
- e.hour = v
- end
- end
- end
-
- if e._comp and e.year
- if e.year >= 0 and e.year <= 99
- if e.year >= 69
- e.year += 1900
- else
- e.year += 2000
- end
- end
- end
-
- e.offset ||= zone_to_diff(e.zone) if e.zone
-
- e.to_hash
- end
-
- def self.zone_to_diff(zone) # :nodoc:
- zone = zone.downcase
- if zone.sub!(/\s+(standard|daylight)\s+time\z/, '')
- dst = $1 == 'daylight'
- else
- dst = zone.sub!(/\s+dst\z/, '')
- end
- if Format::ZONES.include?(zone)
- offset = Format::ZONES[zone]
- offset += 3600 if dst
- elsif zone.sub!(/\A(?:gmt|utc?)?([-+])/, '')
- sign = $1
- if zone.include?(':')
- hour, min, sec, = zone.split(':')
- elsif zone.include?(',') || zone.include?('.')
- hour, fr, = zone.split(/[,.]/)
- min = fr.to_i.to_r / (10**fr.size) * 60
- else
- case zone.size
- when 3
- hour = zone[0,1]
- min = zone[1,2]
- else
- hour = zone[0,2]
- min = zone[2,2]
- sec = zone[4,2]
- end
- end
- offset = hour.to_i * 3600 + min.to_i * 60 + sec.to_i
- offset *= -1 if sign == '-'
- end
- offset
- end
-
-end
-
-class DateTime < Date
-
- def strftime(fmt='%FT%T%:z')
- super(fmt)
- end
-
- def self._strptime(str, fmt='%FT%T%z')
- super(str, fmt)
- end
-
-=begin
- def iso8601_timediv(n) # :nodoc:
- strftime('T%T' +
- if n < 1
- ''
- else
- '.%0*d' % [n, (sec_fraction / (1.to_r/86400/(10**n))).round]
- end +
- '%:z')
- end
-
- private :iso8601_timediv
-
- def iso8601(n=0)
- super() + iso8601_timediv(n)
- end
-
- def jisx0301(n=0)
- super() + iso8601_timediv(n)
- end
-=end
-
-end
+# format.rb: Written by Tadayoshi Funaba 1999-2006
+# $Id: format.rb,v 2.29 2006-12-30 21:43:41+09 tadf Exp $
+
+require 'rational'
+
+class Date
+
+ module Format # :nodoc:
+
+ MONTHS = {
+ 'january' => 1, 'february' => 2, 'march' => 3, 'april' => 4,
+ 'may' => 5, 'june' => 6, 'july' => 7, 'august' => 8,
+ 'september'=> 9, 'october' =>10, 'november' =>11, 'december' =>12
+ }
+
+ DAYS = {
+ 'sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday'=> 3,
+ 'thursday' => 4, 'friday' => 5, 'saturday' => 6
+ }
+
+ ABBR_MONTHS = {
+ 'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4,
+ 'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8,
+ 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12
+ }
+
+ ABBR_DAYS = {
+ 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
+ 'thu' => 4, 'fri' => 5, 'sat' => 6
+ }
+
+ ZONES = {
+ 'ut' => 0*3600, 'gmt' => 0*3600, 'est' => -5*3600, 'edt' => -4*3600,
+ 'cst' => -6*3600, 'cdt' => -5*3600, 'mst' => -7*3600, 'mdt' => -6*3600,
+ 'pst' => -8*3600, 'pdt' => -7*3600,
+ 'a' => 1*3600, 'b' => 2*3600, 'c' => 3*3600, 'd' => 4*3600,
+ 'e' => 5*3600, 'f' => 6*3600, 'g' => 7*3600, 'h' => 8*3600,
+ 'i' => 9*3600, 'k' => 10*3600, 'l' => 11*3600, 'm' => 12*3600,
+ 'n' => -1*3600, 'o' => -2*3600, 'p' => -3*3600, 'q' => -4*3600,
+ 'r' => -5*3600, 's' => -6*3600, 't' => -7*3600, 'u' => -8*3600,
+ 'v' => -9*3600, 'w' =>-10*3600, 'x' =>-11*3600, 'y' =>-12*3600,
+ 'z' => 0*3600,
+ 'utc' => 0*3600, 'wet' => 0*3600, 'bst' => 1*3600, 'wat' => -1*3600,
+ 'at' => -2*3600, 'ast' => -4*3600, 'adt' => -3*3600, 'yst' => -9*3600,
+ 'ydt' => -8*3600, 'hst' =>-10*3600, 'hdt' => -9*3600, 'cat' =>-10*3600,
+ 'ahst'=>-10*3600, 'nt' =>-11*3600, 'idlw'=>-12*3600, 'cet' => 1*3600,
+ 'met' => 1*3600, 'mewt'=> 1*3600, 'mest'=> 2*3600, 'mesz'=> 2*3600,
+ 'swt' => 1*3600, 'sst' => 2*3600, 'fwt' => 1*3600, 'fst' => 2*3600,
+ 'eet' => 2*3600, 'bt' => 3*3600, 'zp4' => 4*3600, 'zp5' => 5*3600,
+ 'zp6' => 6*3600, 'wast'=> 7*3600, 'wadt'=> 8*3600, 'cct' => 8*3600,
+ 'jst' => 9*3600, 'east'=> 10*3600, 'eadt'=> 11*3600, 'gst' => 10*3600,
+ 'nzt' => 12*3600, 'nzst'=> 12*3600, 'nzdt'=> 13*3600, 'idle'=> 12*3600,
+
+ 'afghanistan' => 16200, 'alaskan' => -32400,
+ 'arab' => 10800, 'arabian' => 14400,
+ 'arabic' => 10800, 'atlantic' => -14400,
+ 'aus central' => 34200, 'aus eastern' => 36000,
+ 'azores' => -3600, 'canada central' => -21600,
+ 'cape verde' => -3600, 'caucasus' => 14400,
+ 'cen. australia' => 34200, 'central america' => -21600,
+ 'central asia' => 21600, 'central europe' => 3600,
+ 'central european' => 3600, 'central pacific' => 39600,
+ 'central' => -21600, 'china' => 28800,
+ 'dateline' => -43200, 'e. africa' => 10800,
+ 'e. australia' => 36000, 'e. europe' => 7200,
+ 'e. south america' => -10800, 'eastern' => -18000,
+ 'egypt' => 7200, 'ekaterinburg' => 18000,
+ 'fiji' => 43200, 'fle' => 7200,
+ 'greenland' => -10800, 'greenwich' => 0,
+ 'gtb' => 7200, 'hawaiian' => -36000,
+ 'india' => 19800, 'iran' => 12600,
+ 'jerusalem' => 7200, 'korea' => 32400,
+ 'mexico' => -21600, 'mid-atlantic' => -7200,
+ 'mountain' => -25200, 'myanmar' => 23400,
+ 'n. central asia' => 21600, 'nepal' => 20700,
+ 'new zealand' => 43200, 'newfoundland' => -12600,
+ 'north asia east' => 28800, 'north asia' => 25200,
+ 'pacific sa' => -14400, 'pacific' => -28800,
+ 'romance' => 3600, 'russian' => 10800,
+ 'sa eastern' => -10800, 'sa pacific' => -18000,
+ 'sa western' => -14400, 'samoa' => -39600,
+ 'se asia' => 25200, 'malay peninsula' => 28800,
+ 'south africa' => 7200, 'sri lanka' => 21600,
+ 'taipei' => 28800, 'tasmania' => 36000,
+ 'tokyo' => 32400, 'tonga' => 46800,
+ 'us eastern' => -18000, 'us mountain' => -25200,
+ 'vladivostok' => 36000, 'w. australia' => 28800,
+ 'w. central africa' => 3600, 'w. europe' => 3600,
+ 'west asia' => 18000, 'west pacific' => 36000,
+ 'yakutsk' => 32400
+ }
+
+ [MONTHS, DAYS, ABBR_MONTHS, ABBR_DAYS, ZONES].each do |x|
+ x.freeze
+ end
+
+ class Bag # :nodoc:
+
+ def method_missing(t, *args, &block)
+ t = t.to_s
+ set = t.chomp!('=')
+ t = '@' + t
+ if set
+ instance_variable_set(t, *args)
+ else
+ if instance_variables.include?(t)
+ instance_variable_get(t)
+ end
+ end
+ end
+
+ def to_hash
+ instance_variables.
+ select{|n| !instance_variable_get(n).nil?}.grep(/\A@[^_]/).
+ inject({}){|r, n| r[n[1..-1].intern] = instance_variable_get(n); r}
+ end
+
+ end
+
+ end
+
+ def emit(e, f) # :nodoc:
+ case e
+ when Numeric
+ sign = %w(+ + -)[e <=> 0]
+ e = e.abs
+ end
+
+ s = e.to_s
+
+ if f[:s] && f[:p] == '0'
+ f[:w] -= 1
+ end
+
+ if f[:s] && f[:p] == "\s"
+ s[0,0] = sign
+ end
+
+ if f[:p] != '-'
+ s = s.rjust(f[:w], f[:p])
+ end
+
+ if f[:s] && f[:p] != "\s"
+ s[0,0] = sign
+ end
+
+ s = s.upcase if f[:u]
+ s = s.downcase if f[:d]
+ s
+ end
+
+ def emit_w(e, w, f) # :nodoc:
+ f[:w] = [f[:w], w].compact.max
+ emit(e, f)
+ end
+
+ def emit_n(e, w, f) # :nodoc:
+ f[:p] ||= '0'
+ emit_w(e, w, f)
+ end
+
+ def emit_sn(e, w, f) # :nodoc:
+ if e < 0
+ w += 1
+ f[:s] = true
+ end
+ emit_n(e, w, f)
+ end
+
+ def emit_z(e, w, f) # :nodoc:
+ w += 1
+ f[:s] = true
+ emit_n(e, w, f)
+ end
+
+ def emit_a(e, w, f) # :nodoc:
+ f[:p] ||= "\s"
+ emit_w(e, w, f)
+ end
+
+ def emit_ad(e, w, f) # :nodoc:
+ if f[:x]
+ f[:u] = true
+ f[:d] = false
+ end
+ emit_a(e, w, f)
+ end
+
+ def emit_au(e, w, f) # :nodoc:
+ if f[:x]
+ f[:u] = false
+ f[:d] = true
+ end
+ emit_a(e, w, f)
+ end
+
+ private :emit, :emit_w, :emit_n, :emit_sn, :emit_z,
+ :emit_a, :emit_ad, :emit_au
+
+ def strftime(fmt='%F')
+ fmt.gsub(/%([-_0^#]+)?(\d+)?[EO]?(:{1,3}z|.)/m) do |m|
+ f = {}
+ s, w, c = $1, $2, $3
+ if s
+ s.scan(/./) do |k|
+ case k
+ when '-'; f[:p] = '-'
+ when '_'; f[:p] = "\s"
+ when '0'; f[:p] = '0'
+ when '^'; f[:u] = true
+ when '#'; f[:x] = true
+ end
+ end
+ end
+ if w
+ f[:w] = w.to_i
+ end
+ case c
+ when 'A'; emit_ad(DAYNAMES[wday], 0, f)
+ when 'a'; emit_ad(ABBR_DAYNAMES[wday], 0, f)
+ when 'B'; emit_ad(MONTHNAMES[mon], 0, f)
+ when 'b'; emit_ad(ABBR_MONTHNAMES[mon], 0, f)
+ when 'C'; emit_sn((year / 100).floor, 2, f)
+ when 'c'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 0, f)
+ when 'D'; emit_a(strftime('%m/%d/%y'), 0, f)
+ when 'd'; emit_n(mday, 2, f)
+ when 'e'; emit_a(mday, 2, f)
+ when 'F'
+ if m == '%F'
+ format('%.4d-%02d-%02d', year, mon, mday) # 4p
+ else
+ emit_a(strftime('%Y-%m-%d'), 0, f)
+ end
+ when 'G'; emit_sn(cwyear, 4, f)
+ when 'g'; emit_n(cwyear % 100, 2, f)
+ when 'H'; emit_n(hour, 2, f)
+ when 'h'; emit_ad(strftime('%b'), 0, f)
+ when 'I'; emit_n((hour % 12).nonzero? || 12, 2, f)
+ when 'j'; emit_n(yday, 3, f)
+ when 'k'; emit_a(hour, 2, f)
+ when 'L'
+ emit_n((sec_fraction / (1.to_r/(10**3))).round, 3, f)
+ when 'l'; emit_a((hour % 12).nonzero? || 12, 2, f)
+ when 'M'; emit_n(min, 2, f)
+ when 'm'; emit_n(mon, 2, f)
+ when 'N'
+ emit_n((sec_fraction / (1.to_r/(10**9))).round, 9, f)
+ when 'n'; "\n"
+ when 'P'; emit_ad(strftime('%p').downcase, 0, f)
+ when 'p'; emit_au(if hour < 12 then 'AM' else 'PM' end, 0, f)
+ when 'Q'
+ d = ajd - jd_to_ajd(self.class::UNIXEPOCH, 0)
+ s = (d * 86400*10**3).to_i
+ emit_sn(s, 1, f)
+ when 'R'; emit_a(strftime('%H:%M'), 0, f)
+ when 'r'; emit_a(strftime('%I:%M:%S %p'), 0, f)
+ when 'S'; emit_n(sec, 2, f)
+ when 's'
+ d = ajd - jd_to_ajd(self.class::UNIXEPOCH, 0)
+ s = (d * 86400).to_i
+ emit_sn(s, 1, f)
+ when 'T'
+ if m == '%T'
+ format('%02d:%02d:%02d', hour, min, sec) # 4p
+ else
+ emit_a(strftime('%H:%M:%S'), 0, f)
+ end
+ when 't'; "\t"
+ when 'U', 'W'
+ emit_n(if c == 'U' then wnum0 else wnum1 end, 2, f)
+ when 'u'; emit_n(cwday, 1, f)
+ when 'V'; emit_n(cweek, 2, f)
+ when 'v'; emit_a(strftime('%e-%b-%Y'), 0, f)
+ when 'w'; emit_n(wday, 1, f)
+ when 'X'; emit_a(strftime('%H:%M:%S'), 0, f)
+ when 'x'; emit_a(strftime('%m/%d/%y'), 0, f)
+ when 'Y'; emit_sn(year, 4, f)
+ when 'y'; emit_n(year % 100, 2, f)
+ when 'Z'; emit_au(strftime('%:z'), 0, f)
+ when /\A(:{0,3})z/
+ t = $1.size
+ sign = if offset < 0 then -1 else +1 end
+ fr = offset.abs
+ hh, fr = fr.divmod(1.to_r/24)
+ mm, fr = fr.divmod(1.to_r/1440)
+ ss, fr = fr.divmod(1.to_r/86400)
+ if t == 3
+ if ss.nonzero? then t = 2
+ elsif mm.nonzero? then t = 1
+ else t = -1
+ end
+ end
+ case t
+ when -1
+ tail = []
+ sep = ''
+ when 0
+ f[:w] -= 2 if f[:w]
+ tail = ['%02d' % mm]
+ sep = ''
+ when 1
+ f[:w] -= 3 if f[:w]
+ tail = ['%02d' % mm]
+ sep = ':'
+ when 2
+ f[:w] -= 6 if f[:w]
+ tail = ['%02d' % mm, '%02d' % ss]
+ sep = ':'
+ end
+ ([emit_z(sign * hh, 2, f)] + tail).join(sep)
+ when '%'; emit_a('%', 0, f)
+ when '+'; emit_a(strftime('%a %b %e %H:%M:%S %Z %Y'), 0, f)
+ else
+ c
+ end
+ end
+ end
+
+# alias_method :format, :strftime
+
+ def asctime() strftime('%c') end
+
+ alias_method :ctime, :asctime
+
+ def iso8601() strftime('%F') end
+
+ def rfc3339() iso8601 end
+
+ def rfc2822() strftime('%a, %-d %b %Y %T %z') end
+
+ alias_method :rfc822, :rfc2822
+
+ def jisx0301
+ if jd < 2405160
+ iso8601
+ else
+ case jd
+ when 2405160...2419614
+ g = 'M%02d' % (year - 1867)
+ when 2419614...2424875
+ g = 'T%02d' % (year - 1911)
+ when 2424875...2447535
+ g = 'S%02d' % (year - 1925)
+ else
+ g = 'H%02d' % (year - 1988)
+ end
+ g + strftime('.%m.%d')
+ end
+ end
+
+=begin
+ def beat(n=0)
+ i, f = (new_offset(1.to_r/24).day_fraction * 1000).divmod(1)
+ ('@%03d' % i) +
+ if n < 1
+ ''
+ else
+ '.%0*d' % [n, (f / (1.to_r/(10**n))).round]
+ end
+ end
+=end
+
+ def self.num_pattern? (s) # :nodoc:
+ /\A%[EO]?[CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy\d]/ =~ s || /\A\d/ =~ s
+ end
+
+ private_class_method :num_pattern?
+
+ def self._strptime_i(str, fmt, e) # :nodoc:
+ fmt.scan(/%[EO]?(:{1,3}z|.)|(.)/m) do |s, c|
+ if s
+ case s
+ when 'A', 'a'
+ return unless str.sub!(/\A(#{Format::DAYS.keys.join('|')})/io, '') ||
+ str.sub!(/\A(#{Format::ABBR_DAYS.keys.join('|')})/io, '')
+ val = Format::DAYS[$1.downcase] || Format::ABBR_DAYS[$1.downcase]
+ return unless val
+ e.wday = val
+ when 'B', 'b', 'h'
+ return unless str.sub!(/\A(#{Format::MONTHS.keys.join('|')})/io, '') ||
+ str.sub!(/\A(#{Format::ABBR_MONTHS.keys.join('|')})/io, '')
+ val = Format::MONTHS[$1.downcase] || Format::ABBR_MONTHS[$1.downcase]
+ return unless val
+ e.mon = val
+ when 'C'
+ return unless str.sub!(if num_pattern?($')
+ then /\A([-+]?\d{1,2})/
+ else /\A([-+]?\d{1,})/
+ end, '')
+ val = $1.to_i
+ e._cent = val
+ when 'c'
+ return unless _strptime_i(str, '%a %b %e %H:%M:%S %Y', e)
+ when 'D'
+ return unless _strptime_i(str, '%m/%d/%y', e)
+ when 'd', 'e'
+ return unless str.sub!(/\A( \d|\d{1,2})/, '')
+ val = $1.to_i
+ return unless (1..31) === val
+ e.mday = val
+ when 'F'
+ return unless _strptime_i(str, '%Y-%m-%d', e)
+ when 'G'
+ return unless str.sub!(if num_pattern?($')
+ then /\A([-+]?\d{1,4})/
+ else /\A([-+]?\d{1,})/
+ end, '')
+ val = $1.to_i
+ e.cwyear = val
+ when 'g'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (0..99) === val
+ e.cwyear = val
+ e._cent ||= if val >= 69 then 19 else 20 end
+ when 'H', 'k'
+ return unless str.sub!(/\A( \d|\d{1,2})/, '')
+ val = $1.to_i
+ return unless (0..24) === val
+ e.hour = val
+ when 'I', 'l'
+ return unless str.sub!(/\A( \d|\d{1,2})/, '')
+ val = $1.to_i
+ return unless (1..12) === val
+ e.hour = val
+ when 'j'
+ return unless str.sub!(/\A(\d{1,3})/, '')
+ val = $1.to_i
+ return unless (1..366) === val
+ e.yday = val
+ when 'L'
+ return unless str.sub!(if num_pattern?($')
+ then /\A([-+]?\d{1,3})/
+ else /\A([-+]?\d{1,})/
+ end, '')
+# val = $1.to_i.to_r / (10**3)
+ val = $1.to_i.to_r / (10**$1.size)
+ e.sec_fraction = val
+ when 'M'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (0..59) === val
+ e.min = val
+ when 'm'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (1..12) === val
+ e.mon = val
+ when 'N'
+ return unless str.sub!(if num_pattern?($')
+ then /\A([-+]?\d{1,9})/
+ else /\A([-+]?\d{1,})/
+ end, '')
+# val = $1.to_i.to_r / (10**9)
+ val = $1.to_i.to_r / (10**$1.size)
+ e.sec_fraction = val
+ when 'n', 't'
+ return unless _strptime_i(str, "\s", e)
+ when 'P', 'p'
+ return unless str.sub!(/\A([ap])(?:m\b|\.m\.)/i, '')
+ e._merid = if $1.downcase == 'a' then 0 else 12 end
+ when 'Q'
+ return unless str.sub!(/\A(-?\d{1,})/, '')
+ val = $1.to_i.to_r / 10**3
+ e.seconds = val
+ when 'R'
+ return unless _strptime_i(str, '%H:%M', e)
+ when 'r'
+ return unless _strptime_i(str, '%I:%M:%S %p', e)
+ when 'S'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (0..60) === val
+ e.sec = val
+ when 's'
+ return unless str.sub!(/\A(-?\d{1,})/, '')
+ val = $1.to_i
+ e.seconds = val
+ when 'T'
+ return unless _strptime_i(str, '%H:%M:%S', e)
+ when 'U', 'W'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (0..53) === val
+ e.__send__(if s == 'U' then :wnum0= else :wnum1= end, val)
+ when 'u'
+ return unless str.sub!(/\A(\d{1})/, '')
+ val = $1.to_i
+ return unless (1..7) === val
+ e.cwday = val
+ when 'V'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (1..53) === val
+ e.cweek = val
+ when 'v'
+ return unless _strptime_i(str, '%e-%b-%Y', e)
+ when 'w'
+ return unless str.sub!(/\A(\d{1})/, '')
+ val = $1.to_i
+ return unless (0..6) === val
+ e.wday = val
+ when 'X'
+ return unless _strptime_i(str, '%H:%M:%S', e)
+ when 'x'
+ return unless _strptime_i(str, '%m/%d/%y', e)
+ when 'Y'
+ return unless str.sub!(if num_pattern?($')
+ then /\A([-+]?\d{1,4})/
+ else /\A([-+]?\d{1,})/
+ end, '')
+ val = $1.to_i
+ e.year = val
+ when 'y'
+ return unless str.sub!(/\A(\d{1,2})/, '')
+ val = $1.to_i
+ return unless (0..99) === val
+ e.year = val
+ e._cent ||= if val >= 69 then 19 else 20 end
+ when 'Z', /\A:{0,3}z/
+ return unless str.sub!(/\A((?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
+ |[a-z.\s]+(?:standard|daylight)\s+time\b
+ |[a-z]+(?:\s+dst)?\b
+ )/ix, '')
+ val = $1
+ e.zone = val
+ offset = zone_to_diff(val)
+ e.offset = offset
+ when '%'
+ return unless str.sub!(/\A%/, '')
+ when '+'
+ return unless _strptime_i(str, '%a %b %e %H:%M:%S %Z %Y', e)
+ else
+ return unless str.sub!(Regexp.new('\\A' + Regexp.quote(s)), '')
+ end
+ else
+ case c
+ when /\A[\s\v]/
+ str.sub!(/\A[\s\v]+/, '')
+ else
+ return unless str.sub!(Regexp.new('\\A' + Regexp.quote(c)), '')
+ end
+ end
+ end
+ end
+
+ private_class_method :_strptime_i
+
+ def self._strptime(str, fmt='%F')
+ e = Format::Bag.new
+ return unless _strptime_i(str.dup, fmt, e)
+
+ if e._cent
+ if e.cwyear
+ e.cwyear += e._cent * 100
+ end
+ if e.year
+ e. year += e._cent * 100
+ end
+ end
+
+ if e._merid
+ if e.hour
+ e.hour %= 12
+ e.hour += e._merid
+ end
+ end
+
+ e.to_hash
+ end
+
+ def self.s3e(e, y, m, d, bc=false)
+ unless String === m
+ m = m.to_s
+ end
+
+ if y == nil
+ if d && d.size > 2
+ y = d
+ d = nil
+ end
+ if d && d[0,1] == "'"
+ y = d
+ d = nil
+ end
+ end
+
+ if y
+ y.scan(/(\d+)(.+)?/)
+ if $2
+ y, d = d, $1
+ end
+ end
+
+ if m
+ if m[0,1] == "'" || m.size > 2
+ y, m, d = m, d, y # us -> be
+ end
+ end
+
+ if d
+ if d[0,1] == "'" || d.size > 2
+ y, d = d, y
+ end
+ end
+
+ if y
+ y =~ /([-+])?(\d+)/
+ if $1 || $2.size > 2
+ c = false
+ end
+ iy = $&.to_i
+ if bc
+ iy = -iy + 1
+ end
+ e.year = iy
+ end
+
+ if m
+ m =~ /\d+/
+ e.mon = $&.to_i
+ end
+
+ if d
+ d =~ /\d+/
+ e.mday = $&.to_i
+ end
+
+ if c != nil
+ e._comp = c
+ end
+
+ end
+
+ private_class_method :s3e
+
+ def self._parse_day(str, e) # :nodoc:
+ if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/ino, ' ')
+ e.wday = Format::ABBR_DAYS[$1.downcase]
+ true
+=begin
+ elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/in, ' ')
+ e.wday = %w(su mo tu we th fr sa).index($1.downcase)
+ true
+=end
+ end
+ end
+
+ def self._parse_time(str, e) # :nodoc:
+ if str.sub!(
+ /(
+ (?:
+ \d+\s*:\s*\d+
+ (?:
+ \s*:\s*\d+(?:[,.]\d*)?
+ )?
+ |
+ \d+\s*h(?:\s*\d+m?(?:\s*\d+s?)?)?
+ )
+ (?:
+ \s*
+ [ap](?:m\b|\.m\.)
+ )?
+ |
+ \d+\s*[ap](?:m\b|\.m\.)
+ )
+ (?:
+ \s*
+ (
+ (?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
+ |
+ [a-z.\s]+(?:standard|daylight)\stime\b
+ |
+ [a-z]+(?:\sdst)?\b
+ )
+ )?
+ /inx,
+ ' ')
+
+ t = $1
+ e.zone = $2 if $2
+
+ t =~ /\A(\d+)h?
+ (?:\s*:?\s*(\d+)m?
+ (?:
+ \s*:?\s*(\d+)(?:[,.](\d+))?s?
+ )?
+ )?
+ (?:\s*([ap])(?:m\b|\.m\.))?/inx
+
+ e.hour = $1.to_i
+ e.min = $2.to_i if $2
+ e.sec = $3.to_i if $3
+ e.sec_fraction = $4.to_i.to_r / (10**$4.size) if $4
+
+ if $5
+ e.hour %= 12
+ if $5.downcase == 'p'
+ e.hour += 12
+ end
+ end
+ true
+ end
+ end
+
+ def self._parse_beat(str, e) # :nodoc:
+ if str.sub!(/ \s*(\d+)(?:[,.](\d*))?/, ' ')
+ beat = $1.to_i.to_r
+ beat += $2.to_i.to_r / (10**$2.size) if $2
+ secs = beat.to_r / 1000
+ h, min, s, fr = self.day_fraction_to_time(secs)
+ e.hour = h
+ e.min = min
+ e.sec = s
+ e.sec_fraction = fr * 86400
+ e.zone = '+01:00'
+ true
+ end
+ end
+
+ def self._parse_eu(str, e) # :nodoc:
+ if str.sub!(
+ /'?(\d+)[^-\d\s]*
+ \s*
+ (#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
+ (?:
+ \s*
+ (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
+ \s*
+ ('?-?\d+(?:(?:st|nd|rd|th)\b)?)
+ )?
+ /inox,
+ ' ') # '
+ s3e(e, $4, Format::ABBR_MONTHS[$2.downcase], $1,
+ $3 && $3[0,1].downcase == 'b')
+ true
+ end
+ end
+
+ def self._parse_us(str, e) # :nodoc:
+ if str.sub!(
+ /\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
+ \s*
+ ('?\d+)[^-\d\s']*
+ (?:
+ \s*
+ (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
+ \s*
+ ('?-?\d+)
+ )?
+ /inox,
+ ' ') # '
+ s3e(e, $4, Format::ABBR_MONTHS[$1.downcase], $2,
+ $3 && $3[0,1].downcase == 'b')
+ true
+ end
+ end
+
+ def self._parse_iso(str, e) # :nodoc:
+ if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)/n, ' ')
+ s3e(e, $1, $2, $3)
+ true
+ end
+ end
+
+ def self._parse_iso2(str, e) # :nodoc:
+ if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d+))?/in, ' ')
+ e.cwyear = $1.to_i if $1
+ e.cweek = $2.to_i
+ e.cwday = $3.to_i if $3
+ true
+ elsif str.sub!(/--(\d{2})-(\d{2})\b/n, ' ')
+ e.mon = $1.to_i
+ e.mday = $2.to_i
+ true
+ elsif str.sub!(/\b(\d{2}|\d{4})-(\d{2,3})\b/n, ' ')
+ e.year = $1.to_i
+ if $2.size < 3
+ e.mon = $2.to_i
+ else
+ e.yday = $2.to_i
+ end
+ true
+ end
+ end
+
+ def self._parse_jis(str, e) # :nodoc:
+ if str.sub!(/\b([MTSH])(\d+)\.(\d+)\.(\d+)/in, ' ')
+ era = { 'm'=>1867,
+ 't'=>1911,
+ 's'=>1925,
+ 'h'=>1988
+ }[$1.downcase]
+ e.year = $2.to_i + era
+ e.mon = $3.to_i
+ e.mday = $4.to_i
+ true
+ end
+ end
+
+ def self._parse_vms(str, e) # :nodoc:
+ if str.sub!(/('?-?\d+)-(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
+ -('?-?\d+)/inox, ' ')
+ s3e(e, $3, Format::ABBR_MONTHS[$2.downcase], $1)
+ true
+ elsif str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
+ -('?-?\d+)(?:-('?-?\d+))?/inox, ' ')
+ s3e(e, $3, Format::ABBR_MONTHS[$1.downcase], $2)
+ true
+ end
+ end
+
+ def self._parse_sla_ja(str, e) # :nodoc:
+ if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
+ s3e(e, $1, $2, $3)
+ true
+ end
+ end
+
+ def self._parse_sla_eu(str, e) # :nodoc:
+ if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
+ s3e(e, $3, $2, $1)
+ true
+ end
+ end
+
+ def self._parse_sla_us(str, e) # :nodoc:
+ if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
+ s3e(e, $3, $1, $2)
+ true
+ end
+ end
+
+ def self._parse_year(str, e) # :nodoc:
+ if str.sub!(/'(\d+)\b/in, ' ')
+ e.year = $1.to_i
+ true
+ end
+ end
+
+ def self._parse_mon(str, e) # :nodoc:
+ if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/ino, ' ')
+ e.mon = Format::ABBR_MONTHS[$1.downcase]
+ true
+ end
+ end
+
+ def self._parse_mday(str, e) # :nodoc:
+ if str.sub!(/(\d+)(st|nd|rd|th)\b/in, ' ')
+ e.mday = $1.to_i
+ true
+ end
+ end
+
+ def self._parse_ddd(str, e) # :nodoc:
+ if str.sub!(
+ /([-+]?)(\d{2,14})
+ (?:
+ \s*
+ T?
+ \s*
+ (\d{2,6})(?:[,.](\d*))?
+ )?
+ (?:
+ \s*
+ (
+ Z
+ |
+ [-+]\d{1,4}
+ )
+ \b
+ )?
+ /inx,
+ ' ')
+ case $2.size
+ when 2
+ e.mday = $2[ 0, 2].to_i
+ when 4
+ e.mon = $2[ 0, 2].to_i
+ e.mday = $2[ 2, 2].to_i
+ when 6
+ e.year = ($1 + $2[ 0, 2]).to_i
+ e.mon = $2[ 2, 2].to_i
+ e.mday = $2[ 4, 2].to_i
+ when 8, 10, 12, 14
+ e.year = ($1 + $2[ 0, 4]).to_i
+ e.mon = $2[ 4, 2].to_i
+ e.mday = $2[ 6, 2].to_i
+ e.hour = $2[ 8, 2].to_i if $2.size >= 10
+ e.min = $2[10, 2].to_i if $2.size >= 12
+ e.sec = $2[12, 2].to_i if $2.size >= 14
+ e._comp = false
+ when 3
+ e.yday = $2[ 0, 3].to_i
+ when 5
+ e.year = ($1 + $2[ 0, 2]).to_i
+ e.yday = $2[ 2, 3].to_i
+ when 7
+ e.year = ($1 + $2[ 0, 4]).to_i
+ e.yday = $2[ 4, 3].to_i
+ end
+ if $3
+ case $3.size
+ when 2, 4, 6
+ e.hour = $3[ 0, 2].to_i
+ e.min = $3[ 2, 2].to_i if $3.size >= 4
+ e.sec = $3[ 4, 2].to_i if $3.size >= 6
+ end
+ end
+ if $4
+ e.sec_fraction = $4.to_i.to_r / (10**$4.size)
+ end
+ if $5
+ e.zone = $5
+ end
+ true
+ end
+ end
+
+ private_class_method :_parse_day, :_parse_time, :_parse_beat,
+ :_parse_eu, :_parse_us, :_parse_iso, :_parse_iso2,
+ :_parse_jis, :_parse_vms,
+ :_parse_sla_ja, :_parse_sla_eu, :_parse_sla_us,
+ :_parse_year, :_parse_mon, :_parse_mday, :_parse_ddd
+
+ def self._parse(str, comp=false)
+ str = str.dup
+
+ e = Format::Bag.new
+
+ e._comp = comp
+
+ str.gsub!(/[^-+',.\/:0-9@a-z\x80-\xff]+/in, ' ')
+
+ _parse_time(str, e) # || _parse_beat(str, e)
+ _parse_day(str, e)
+
+ _parse_eu(str, e) ||
+ _parse_us(str, e) ||
+ _parse_iso(str, e) ||
+ _parse_jis(str, e) ||
+ _parse_vms(str, e) ||
+ _parse_sla_us(str, e) ||
+ _parse_iso2(str, e) ||
+ _parse_year(str, e) ||
+ _parse_mon(str, e) ||
+ _parse_mday(str, e) ||
+ _parse_ddd(str, e)
+
+ if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/in, ' ')
+ if e.year
+ e.year = -e.year + 1
+ end
+ end
+
+ if str.sub!(/\A\s*(\d{1,2})\s*\z/n, ' ')
+ if e.hour && !e.mday
+ v = $1.to_i
+ if (1..31) === v
+ e.mday = v
+ end
+ end
+ if e.mday && !e.hour
+ v = $1.to_i
+ if (0..24) === v
+ e.hour = v
+ end
+ end
+ end
+
+ if e._comp and e.year
+ if e.year >= 0 and e.year <= 99
+ if e.year >= 69
+ e.year += 1900
+ else
+ e.year += 2000
+ end
+ end
+ end
+
+ e.offset ||= zone_to_diff(e.zone) if e.zone
+
+ e.to_hash
+ end
+
+ t = Module.new do
+
+ private
+
+ def zone_to_diff(zone) # :nodoc:
+ zone = zone.downcase
+ if zone.sub!(/\s+(standard|daylight)\s+time\z/, '')
+ dst = $1 == 'daylight'
+ else
+ dst = zone.sub!(/\s+dst\z/, '')
+ end
+ if Format::ZONES.include?(zone)
+ offset = Format::ZONES[zone]
+ offset += 3600 if dst
+ elsif zone.sub!(/\A(?:gmt|utc?)?([-+])/, '')
+ sign = $1
+ if zone.include?(':')
+ hour, min, sec, = zone.split(':')
+ elsif zone.include?(',') || zone.include?('.')
+ hour, fr, = zone.split(/[,.]/)
+ min = fr.to_i.to_r / (10**fr.size) * 60
+ else
+ case zone.size
+ when 3
+ hour = zone[0,1]
+ min = zone[1,2]
+ else
+ hour = zone[0,2]
+ min = zone[2,2]
+ sec = zone[4,2]
+ end
+ end
+ offset = hour.to_i * 3600 + min.to_i * 60 + sec.to_i
+ offset *= -1 if sign == '-'
+ end
+ offset
+ end
+
+ end
+
+ extend t
+ include t
+
+end
+
+class DateTime < Date
+
+ def strftime(fmt='%FT%T%:z')
+ super(fmt)
+ end
+
+ def self._strptime(str, fmt='%FT%T%z')
+ super(str, fmt)
+ end
+
+ def iso8601_timediv(n) # :nodoc:
+ strftime('T%T' +
+ if n < 1
+ ''
+ else
+ '.%0*d' % [n, (sec_fraction / (1.to_r/(10**n))).round]
+ end +
+ '%:z')
+ end
+
+ private :iso8601_timediv
+
+ def iso8601(n=0)
+ super() + iso8601_timediv(n)
+ end
+
+ def jisx0301(n=0)
+ super() + iso8601_timediv(n)
+ end
+
+end
Modified: trunk/lib/date.rb
===================================================================
--- trunk/lib/date.rb 2006-12-29 23:13:35 UTC (rev 587)
+++ trunk/lib/date.rb 2006-12-31 08:05:21 UTC (rev 588)
@@ -1,1656 +1,1713 @@
-#
-# date.rb - date and time library
-#
-# Author: Tadayoshi Funaba 1998-2006
-#
-# Documentation: William Webber <william williamwebber.com>
-#
-#--
-# $Id: date.rb,v 2.29 2006-11-05 18:21:29+09 tadf Exp $
-#++
-#
-# == Overview
-#
-# This file provides two classes for working with
-# dates and times.
-#
-# The first class, Date, represents dates.
-# It works with years, months, weeks, and days.
-# See the Date class documentation for more details.
-#
-# The second, DateTime, extends Date to include hours,
-# minutes, seconds, and fractions of a second. It
-# provides basic support for time zones. See the
-# DateTime class documentation for more details.
-#
-# === Ways of calculating the date.
-#
-# In common usage, the date is reckoned in years since or
-# before the Common Era (CE/BCE, also known as AD/BC), then
-# as a month and day-of-the-month within the current year.
-# This is known as the *Civil* *Date*, and abbreviated
-# as +civil+ in the Date class.
-#
-# Instead of year, month-of-the-year, and day-of-the-month,
-# the date can also be reckoned in terms of year and
-# day-of-the-year. This is known as the *Ordinal* *Date*,
-# and is abbreviated as +ordinal+ in the Date class. (Note
-# that referring to this as the Julian date is incorrect.)
-#
-# The date can also be reckoned in terms of year, week-of-the-year,
-# and day-of-the-week. This is known as the *Commercial*
-# *Date*, and is abbreviated as +commercial+ in the
-# Date class. The commercial week runs Monday (day-of-the-week
-# 1) to Sunday (day-of-the-week 7), in contrast to the civil
-# week which runs Sunday (day-of-the-week 0) to Saturday
-# (day-of-the-week 6). The first week of the commercial year
-# starts on the Monday on or before January 1, and the commercial
-# year itself starts on this Monday, not January 1.
-#
-# For scientific purposes, it is convenient to refer to a date
-# simply as a day count, counting from an arbitrary initial
-# day. The date first chosen for this was January 1, 4713 BCE.
-# A count of days from this date is the *Julian* *Day* *Number*
-# or *Julian* *Date*, which is abbreviated as +jd+ in the
-# Date class. This is in local time, and counts from midnight
-# on the initial day. The stricter usage is in UTC, and counts
-# from midday on the initial day. This is referred to in the
-# Date class as the *Astronomical* *Julian* *Day* *Number*, and
-# abbreviated as +ajd+. In the Date class, the Astronomical
-# Julian Day Number includes fractional days.
-#
-# Another absolute day count is the *Modified* *Julian* *Day*
-# *Number*, which takes November 17, 1858 as its initial day.
-# This is abbreviated as +mjd+ in the Date class. There
-# is also an *Astronomical* *Modified* *Julian* *Day* *Number*,
-# which is in UTC and includes fractional days. This is
-# abbreviated as +amjd+ in the Date class. Like the Modified
-# Julian Day Number (and unlike the Astronomical Julian
-# Day Number), it counts from midnight.
-#
-# Alternative calendars such as the Chinese Lunar Calendar,
-# the Islamic Calendar, or the French Revolutionary Calendar
-# are not supported by the Date class; nor are calendars that
-# are based on an Era different from the Common Era, such as
-# the Japanese Imperial Calendar or the Republic of China
-# Calendar.
-#
-# === Calendar Reform
-#
-# The standard civil year is 365 days long. However, the
-# solar year is fractionally longer than this. To account
-# for this, a *leap* *year* is occasionally inserted. This
-# is a year with 366 days, the extra day falling on February 29.
-# In the early days of the civil calendar, every fourth
-# year without exception was a leap year. This way of
-# reckoning leap years is the *Julian* *Calendar*.
-#
-# However, the solar year is marginally shorter than 365 1/4
-# days, and so the *Julian* *Calendar* gradually ran slow
-# over the centuries. To correct this, every 100th year
-# (but not every 400th year) was excluded as a leap year.
-# This way of reckoning leap years, which we use today, is
-# the *Gregorian* *Calendar*.
-#
-# The Gregorian Calendar was introduced at different times
-# in different regions. The day on which it was introduced
-# for a particular region is the *Day* *of* *Calendar*
-# *Reform* for that region. This is abbreviated as +sg+
-# (for Start of Gregorian calendar) in the Date class.
-#
-# Two such days are of particular
-# significance. The first is October 15, 1582, which was
-# the Day of Calendar Reform for Italy and most Catholic
-# countries. The second is September 14, 1752, which was
-# the Day of Calendar Reform for England and its colonies
-# (including what is now the United States). These two
-# dates are available as the constants Date::ITALY and
-# Date::ENGLAND, respectively. (By comparison, Germany and
-# Holland, less Catholic than Italy but less stubborn than
-# England, changed over in 1698; Sweden in 1753; Russia not
-# till 1918, after the Revolution; and Greece in 1923. Many
-# Orthodox churches still use the Julian Calendar. A complete
-# list of Days of Calendar Reform can be found at
-# http://www.polysyllabic.com/GregConv.html.)
-#
-# Switching from the Julian to the Gregorian calendar
-# involved skipping a number of days to make up for the
-# accumulated lag, and the later the switch was (or is)
-# done, the more days need to be skipped. So in 1582 in Italy,
-# 4th October was followed by 15th October, skipping 10 days; in 1752
-# in England, 2nd September was followed by 14th September, skipping
-# 11 days; and if I decided to switch from Julian to Gregorian
-# Calendar this midnight, I would go from 27th July 2003 (Julian)
-# today to 10th August 2003 (Gregorian) tomorrow, skipping
-# 13 days. The Date class is aware of this gap, and a supposed
-# date that would fall in the middle of it is regarded as invalid.
-#
-# The Day of Calendar Reform is relevant to all date representations
-# involving years. It is not relevant to the Julian Day Numbers,
-# except for converting between them and year-based representations.
-#
-# In the Date and DateTime classes, the Day of Calendar Reform or
-# +sg+ can be specified a number of ways. First, it can be as
-# the Julian Day Number of the Day of Calendar Reform. Second,
-# it can be using the constants Date::ITALY or Date::ENGLAND; these
-# are in fact the Julian Day Numbers of the Day of Calendar Reform
-# of the respective regions. Third, it can be as the constant
-# Date::JULIAN, which means to always use the Julian Calendar.
-# Finally, it can be as the constant Date::GREGORIAN, which means
-# to always use the Gregorian Calendar.
-#
-# Note: in the Julian Calendar, New Years Day was March 25. The
-# Date class does not follow this convention.
-#
-# === Time Zones
-#
-# DateTime objects support a simple representation
-# of time zones. Time zones are represented as an offset
-# from UTC, as a fraction of a day. This offset is the
-# how much local time is later (or earlier) than UTC.
-# UTC offset 0 is centred on England (also known as GMT).
-# As you travel east, the offset increases until you
-# reach the dateline in the middle of the Pacific Ocean;
-# as you travel west, the offset decreases. This offset
-# is abbreviated as +of+ in the Date class.
-#
-# This simple representation of time zones does not take
-# into account the common practice of Daylight Savings
-# Time or Summer Time.
-#
-# Most DateTime methods return the date and the
-# time in local time. The two exceptions are
-# #ajd() and #amjd(), which return the date and time
-# in UTC time, including fractional days.
-#
-# The Date class does not support time zone offsets, in that
-# there is no way to create a Date object with a time zone.
-# However, methods of the Date class when used by a
-# DateTime instance will use the time zone offset of this
-# instance.
-#
-# == Examples of use
-#
-# === Print out the date of every Sunday between two dates.
-#
-# def print_sundays(d1, d2)
-# d1 +=1 while (d1.wday != 0)
-# d1.step(d2, 7) do |date|
-# puts "#{Date::MONTHNAMES[date.mon]} #{date.day}"
-# end
-# end
-#
-# print_sundays(Date::civil(2003, 4, 8), Date::civil(2003, 5, 23))
-#
-# === Calculate how many seconds to go till midnight on New Year's Day.
-#
-# def secs_to_new_year(now = DateTime::now())
-# new_year = DateTime.new(now.year + 1, 1, 1)
-# dif = new_year - now
-# hours, mins, secs, ignore_fractions = Date::day_fraction_to_time(dif)
-# return hours * 60 * 60 + mins * 60 + secs
-# end
-#
-# puts secs_to_new_year()
-
-require 'rational'
-require 'date/format'
-
-# Class representing a date.
-#
-# See the documentation to the file date.rb for an overview.
-#
-# Internally, the date is represented as an Astronomical
-# Julian Day Number, +ajd+. The Day of Calendar Reform, +sg+, is
-# also stored, for conversions to other date formats. (There
-# is also an +of+ field for a time zone offset, but this
-# is only for the use of the DateTime subclass.)
-#
-# A new Date object is created using one of the object creation
-# class methods named after the corresponding date format, and the
-# arguments appropriate to that date format; for instance,
-# Date::civil() (aliased to Date::new()) with year, month,
-# and day-of-month, or Date::ordinal() with year and day-of-year.
-# All of these object creation class methods also take the
-# Day of Calendar Reform as an optional argument.
-#
-# Date objects are immutable once created.
-#
-# Once a Date has been created, date values
-# can be retrieved for the different date formats supported
-# using instance methods. For instance, #mon() gives the
-# Civil month, #cwday() gives the Commercial day of the week,
-# and #yday() gives the Ordinal day of the year. Date values
-# can be retrieved in any format, regardless of what format
-# was used to create the Date instance.
-#
-# The Date class includes the Comparable module, allowing
-# date objects to be compared and sorted, ranges of dates
-# to be created, and so forth.
-class Date
-
- include Comparable
-
- # Full month names, in English. Months count from 1 to 12; a
- # month's numerical representation indexed into this array
- # gives the name of that month (hence the first element is nil).
- MONTHNAMES = [nil] + %w(January February March April May June July
- August September October November December)
-
- # Full names of days of the week, in English. Days of the week
- # count from 0 to 6 (except in the commercial week); a day's numerical
- # representation indexed into this array gives the name of that day.
- DAYNAMES = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
-
- # Abbreviated month names, in English.
- ABBR_MONTHNAMES = [nil] + %w(Jan Feb Mar Apr May Jun
- Jul Aug Sep Oct Nov Dec)
-
- # Abbreviated day names, in English.
- ABBR_DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
-
- [MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYNAMES].each do |xs|
- xs.each{|x| x.freeze}.freeze
- end
-
- class Infinity < Numeric # :nodoc:
-
- include Comparable
-
- def initialize(d=1) @d = d <=> 0 end
-
- def d() @d end
-
- protected :d
-
- def zero? () false end
- def finite? () false end
- def infinite? () d.nonzero? end
- def nan? () d.zero? end
-
- def abs() self.class.new end
-
- def -@ () self.class.new(-d) end
- def +@ () self.class.new(+d) end
-
- def <=> (other)
- case other
- when Infinity; d <=> other.d
- when Numeric; d
- else
- begin
- l, r = other.coerce(self)
- return l <=> r
- rescue NoMethodError
- end
- end
- nil
- end
-
- def coerce(other)
- case other
- when Numeric; return -d, d
- else
- super
- end
- end
-
- end
-
- # The Julian Day Number of the Day of Calendar Reform for Italy
- # and the Catholic countries.
- ITALY = 2299161 # 1582-10-15
-
- # The Julian Day Number of the Day of Calendar Reform for England
- # and her Colonies.
- ENGLAND = 2361222 # 1752-09-14
-
- # A constant used to indicate that a Date should always use the
- # Julian calendar.
- JULIAN = Infinity.new
-
- # A constant used to indicate that a Date should always use the
- # Gregorian calendar.
- GREGORIAN = -Infinity.new
-
- UNIXEPOCH = 2440588 # 1970-01-01 :nodoc:
-
- # Does a given Julian Day Number fall inside the old-style (Julian)
- # calendar?
- #
- # +jd+ is the Julian Day Number in question. +sg+ may be Date::GREGORIAN,
- # in which case the answer is false; it may be Date::JULIAN, in which case
- # the answer is true; or it may a number representing the Day of
- # Calendar Reform. Date::ENGLAND and Date::ITALY are two possible such
- # days.
- def self.julian? (jd, sg)
- case sg
- when Numeric
- jd < sg
- else
- if $VERBOSE
- warn("#{caller.shift.sub(/:in .*/, '')}: " \
-"warning: do not use non-numerical object as julian day number anymore")
- end
- not sg
- end
- end
-
- # Does a given Julian Day Number fall inside the new-style (Gregorian)
- # calendar?
- #
- # The reverse of self.os? See the documentation for that method for
- # more details.
- def self.gregorian? (jd, sg) not julian?(jd, sg) end
-
- def self.fix_style(jd, sg) # :nodoc:
- if julian?(jd, sg)
- then JULIAN
- else GREGORIAN end
- end
-
- private_class_method :fix_style
-
- # Convert a Civil Date to a Julian Day Number.
- # +y+, +m+, and +d+ are the year, month, and day of the
- # month. +sg+ specifies the Day of Calendar Reform.
- #
- # Returns the corresponding Julian Day Number.
- def self.civil_to_jd(y, m, d, sg=GREGORIAN)
- if m <= 2
- y -= 1
- m += 12
- end
- a = (y / 100.0).floor
- b = 2 - a + (a / 4.0).floor
- jd = (365.25 * (y + 4716)).floor +
- (30.6001 * (m + 1)).floor +
- d + b - 1524
- if julian?(jd, sg)
- jd -= b
- end
- jd
- end
-
- # Convert a Julian Day Number to a Civil Date. +jd+ is
- # the Julian Day Number. +sg+ specifies the Day of
- # Calendar Reform.
- #
- # Returns the corresponding [year, month, day_of_month]
- # as a three-element array.
- def self.jd_to_civil(jd, sg=GREGORIAN)
- if julian?(jd, sg)
- a = jd
- else
- x = ((jd - 1867216.25) / 36524.25).floor
- a = jd + 1 + x - (x / 4.0).floor
- end
- b = a + 1524
- c = ((b - 122.1) / 365.25).floor
- d = (365.25 * c).floor
- e = ((b - d) / 30.6001).floor
- dom = b - d - (30.6001 * e).floor
- if e <= 13
- m = e - 1
- y = c - 4716
- else
- m = e - 13
- y = c - 4715
- end
- return y, m, dom
- end
-
- # Convert a Julian Day Number to an Ordinal Date.
- #
- # +jd+ is the Julian Day Number to convert.
- # +sg+ specifies the Day of Calendar Reform.
- #
- # Returns the corresponding Ordinal Date as
- # [year, day_of_year]
- def self.jd_to_ordinal(jd, sg=GREGORIAN)
- y = jd_to_civil(jd, sg)[0]
- doy = jd - civil_to_jd(y - 1, 12, 31, fix_style(jd, sg))
- return y, doy
- end
-
- # Convert an Ordinal Date to a Julian Day Number.
- #
- # +y+ and +d+ are the year and day-of-year to convert.
- # +sg+ specifies the Day of Calendar Reform.
- #
- # Returns the corresponding Julian Day Number.
- def self.ordinal_to_jd(y, d, sg=GREGORIAN)
- civil_to_jd(y, 1, d, sg)
- end
-
- # Convert a Julian Day Number to a Commercial Date
- #
- # +jd+ is the Julian Day Number to convert.
- # +sg+ specifies the Day of Calendar Reform.
- #
- # Returns the corresponding Commercial Date as
- # [commercial_year, week_of_year, day_of_week]
- def self.jd_to_commercial(jd, sg=GREGORIAN)
- ns = fix_style(jd, sg)
- a = jd_to_civil(jd - 3, ns)[0]
- y = if jd >= commercial_to_jd(a + 1, 1, 1, ns) then a + 1 else a end
- w = 1 + ((jd - commercial_to_jd(y, 1, 1, ns)) / 7).floor
- d = (jd + 1) % 7
- if d.zero? then d = 7 end
- return y, w, d
- end
-
- # Convert a Commercial Date to a Julian Day Number.
- #
- # +y+, +w+, and +d+ are the (commercial) year, week of the year,
- # and day of the week of the Commercial Date to convert.
- # +sg+ specifies the Day of Calendar Reform.
- def self.commercial_to_jd(y, w, d, ns=GREGORIAN)
- jd = civil_to_jd(y, 1, 4, ns)
- (jd - (((jd - 1) + 1) % 7)) +
- 7 * (w - 1) +
- (d - 1)
- end
-
- def self.jd_to_weeknum(jd, k=0, sg=GREGORIAN) # :nodoc:
- ns = fix_style(jd, sg)
- y, m, d = jd_to_civil(jd, ns)
- a = civil_to_jd(y, 1, 1, ns) + 6
- w, d = (jd - (a - ((a - k) + 1) % 7) + 7).divmod(7)
- return y, w, d
- end
-
- def self.weeknum_to_jd(y, w, d, k=0, ns=GREGORIAN) # :nodoc:
- a = civil_to_jd(y, 1, 1, ns) + 6
- (a - ((a - k) + 1) % 7 - 7) + 7 * w + d
- end
-
- # Convert an Astronomical Julian Day Number to a (civil) Julian
- # Day Number.
- #
- # +ajd+ is the Astronomical Julian Day Number to convert.
- # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
- #
- # Returns the (civil) Julian Day Number as [day_number,
- # fraction] where +fraction+ is always 1/2.
- def self.ajd_to_jd(ajd, of=0) (ajd + of + 1.to_r/2).divmod(1) end
-
- # Convert a (civil) Julian Day Number to an Astronomical Julian
- # Day Number.
- #
- # +jd+ is the Julian Day Number to convert, and +fr+ is a
- # fractional day.
- # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
- #
- # Returns the Astronomical Julian Day Number as a single
- # numeric value.
- def self.jd_to_ajd(jd, fr, of=0) jd + fr - of - 1.to_r/2 end
-
- # Convert a fractional day +fr+ to [hours, minutes, seconds,
- # fraction_of_a_second]
- def self.day_fraction_to_time(fr)
- h, fr = fr.divmod(1.to_r/24)
- min, fr = fr.divmod(1.to_r/1440)
- s, fr = fr.divmod(1.to_r/86400)
- return h, min, s, fr
- end
-
- # Convert an +h+ hour, +min+ minutes, +s+ seconds period
- # to a fractional day.
- def self.time_to_day_fraction(h, min, s)
- h.to_r/24 + min.to_r/1440 + s.to_r/86400
- end
-
- # Convert an Astronomical Modified Julian Day Number to an
- # Astronomical Julian Day Number.
- def self.amjd_to_ajd(amjd) amjd + 4800001.to_r/2 end
-
- # Convert an Astronomical Julian Day Number to an
- # Astronomical Modified Julian Day Number.
- def self.ajd_to_amjd(ajd) ajd - 4800001.to_r/2 end
-
- # Convert a Modified Julian Day Number to a Julian
- # Day Number.
- def self.mjd_to_jd(mjd) mjd + 2400001 end
-
- # Convert a Julian Day Number to a Modified Julian Day
- # Number.
- def self.jd_to_mjd(jd) jd - 2400001 end
-
- # Convert a count of the number of days since the adoption
- # of the Gregorian Calendar (in Italy) to a Julian Day Number.
- def self.ld_to_jd(ld) ld + 2299160 end
-
- # Convert a Julian Day Number to the number of days since
- # the adoption of the Gregorian Calendar (in Italy).
- def self.jd_to_ld(jd) jd - 2299160 end
-
- # Convert a Julian Day Number to the day of the week.
- #
- # Sunday is day-of-week 0; Saturday is day-of-week 6.
- def self.jd_to_wday(jd) (jd + 1) % 7 end
-
- # Is a year a leap year in the Julian calendar?
- #
- # All years divisible by 4 are leap years in the Julian calendar.
- def self.julian_leap? (y) y % 4 == 0 end
-
- # Is a year a leap year in the Gregorian calendar?
- #
- # All years divisible by 4 are leap years in the Gregorian calendar,
- # except for years divisible by 100 and not by 400.
- def self.gregorian_leap? (y) y % 4 == 0 and y % 100 != 0 or y % 400 == 0 end
-
- class << self; alias_method :leap?, :gregorian_leap? end
- class << self; alias_method :new0, :new end
-
- # Is +jd+ a valid Julian Day Number?
- #
- # If it is, returns it. In fact, any value is treated as a valid
- # Julian Day Number.
- def self.valid_jd? (jd, sg=ITALY) jd end
-
- # Create a new Date object from a Julian Day Number.
- #
- # +jd+ is the Julian Day Number; if not specified, it defaults to
- # 0.
- # +sg+ specifies the Day of Calendar Reform.
- def self.jd(jd=0, sg=ITALY)
- jd = valid_jd?(jd, sg)
- new0(jd_to_ajd(jd, 0, 0), 0, sg)
- end
-
- # Do t