diff options
Diffstat (limited to 'ext/date')
| -rw-r--r-- | ext/date/date.gemspec | 37 | ||||
| -rw-r--r-- | ext/date/date_core.c | 2576 | ||||
| -rw-r--r-- | ext/date/date_parse.c | 134 | ||||
| -rw-r--r-- | ext/date/date_strftime.c | 2 | ||||
| -rw-r--r-- | ext/date/date_strptime.c | 117 | ||||
| -rw-r--r-- | ext/date/depend | 161 | ||||
| -rw-r--r-- | ext/date/extconf.rb | 8 | ||||
| -rw-r--r-- | ext/date/lib/date.rb | 7 | ||||
| -rw-r--r-- | ext/date/prereq.mk | 9 | ||||
| -rw-r--r-- | ext/date/zonetab.h | 1250 | ||||
| -rw-r--r-- | ext/date/zonetab.list | 9 |
11 files changed, 2458 insertions, 1852 deletions
diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec index 44282759c6..cb439bd0a5 100644 --- a/ext/date/date.gemspec +++ b/ext/date/date.gemspec @@ -1,21 +1,36 @@ # frozen_string_literal: true + +version = File.foreach(File.expand_path("../lib/date.rb", __FILE__)).find do |line| + /^\s*VERSION\s*=\s*["'](.*)["']/ =~ line and break $1 +end + Gem::Specification.new do |s| s.name = "date" - s.version = '3.1.0' - s.summary = "A subclass of Object includes Comparable module for handling dates." - s.description = "A subclass of Object includes Comparable module for handling dates." + s.version = version + s.summary = "The official date library for Ruby." + s.description = "The official date library for Ruby." - s.require_path = %w{lib} - s.files = [ - "lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c", - "ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk", - "ext/date/zonetab.h", "ext/date/zonetab.list" - ] - s.extensions = "ext/date/extconf.rb" - s.required_ruby_version = ">= 2.4.0" + if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby' + s.platform = 'java' + # No files shipped, no require path, no-op for now on JRuby + else + s.require_path = %w{lib} + + s.files = [ + "README.md", "COPYING", "BSDL", + "lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c", + "ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk", + "ext/date/zonetab.h", "ext/date/zonetab.list" + ] + s.extensions = "ext/date/extconf.rb" + end + + s.required_ruby_version = ">= 2.6.0" s.authors = ["Tadayoshi Funaba"] s.email = [nil] s.homepage = "https://github.com/ruby/date" s.licenses = ["Ruby", "BSD-2-Clause"] + + s.metadata["changelog_uri"] = s.homepage + "/releases" end diff --git a/ext/date/date_core.c b/ext/date/date_core.c index 7e9bf16a07..72d697c8ea 100644 --- a/ext/date/date_core.c +++ b/ext/date/date_core.c @@ -27,6 +27,10 @@ static VALUE eDateError; static VALUE half_days_in_day, day_in_nanoseconds; static double positive_inf, negative_inf; +/* used by deconstruct_keys */ +static VALUE sym_year, sym_month, sym_day, sym_yday, sym_wday; +static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone; + #define f_boolcast(x) ((x) ? Qtrue : Qfalse) #define f_abs(x) rb_funcall(x, rb_intern("abs"), 0) @@ -53,14 +57,15 @@ static double positive_inf, negative_inf; #define f_add3(x,y,z) f_add(f_add(x, y), z) #define f_sub3(x,y,z) f_sub(f_sub(x, y), z) -#define f_frozen_ary(...) rb_obj_freeze(rb_ary_new3(__VA_ARGS__)) +#define f_frozen_ary(...) rb_ary_freeze(rb_ary_new3(__VA_ARGS__)) static VALUE date_initialize(int argc, VALUE *argv, VALUE self); static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self); #define RETURN_FALSE_UNLESS_NUMERIC(obj) if(!RTEST(rb_obj_is_kind_of((obj), rb_cNumeric))) return Qfalse inline static void -check_numeric(VALUE obj, const char* field) { +check_numeric(VALUE obj, const char* field) +{ if(!RTEST(rb_obj_is_kind_of(obj, rb_cNumeric))) { rb_raise(rb_eTypeError, "invalid %s (not numeric)", field); } @@ -243,6 +248,11 @@ f_negative_p(VALUE x) #define date_sg_t double #endif +#define JULIAN_EPOCH_DATE "-4712-01-01" +#define JULIAN_EPOCH_DATETIME JULIAN_EPOCH_DATE "T00:00:00+00:00" +#define JULIAN_EPOCH_DATETIME_RFC3339 "Mon, 1 Jan -4712 00:00:00 +0000" +#define JULIAN_EPOCH_DATETIME_HTTPDATE "Mon, 01 Jan -4712 00:00:00 GMT" + /* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at * noon of GMT (assume equal to UTC). However, this begins at * midnight. @@ -442,11 +452,43 @@ do {\ static int c_valid_civil_p(int, int, int, double, int *, int *, int *, int *); +/* Check if using pure Gregorian calendar (sg == -Infinity) */ +#define c_gregorian_only_p(sg) (isinf(sg) && (sg) < 0) + +/* + * Fast path macros for pure Gregorian calendar. + * Sets *rjd to the JD value, *ns to 1 (new style), and returns. + */ +#define GREGORIAN_JD_FAST_PATH_RET(sg, jd_expr, rjd, ns) \ + if (c_gregorian_only_p(sg)) { \ + *(rjd) = (jd_expr); \ + *(ns) = 1; \ + return 1; \ + } + +#define GREGORIAN_JD_FAST_PATH(sg, jd_expr, rjd, ns) \ + if (c_gregorian_only_p(sg)) { \ + *(rjd) = (jd_expr); \ + *(ns) = 1; \ + return; \ + } + +/* Forward declarations for Neri-Schneider optimized functions */ +static int c_gregorian_civil_to_jd(int y, int m, int d); +static void c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd); +static int c_gregorian_fdoy(int y); +static int c_gregorian_ldoy(int y); +static int c_gregorian_ldom_jd(int y, int m); +static int ns_jd_in_range(int jd); + static int c_find_fdoy(int y, double sg, int *rjd, int *ns) { int d, rm, rd; + GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_fdoy(y), rjd, ns); + + /* Keep existing loop for Julian/reform period */ for (d = 1; d < 31; d++) if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns)) return 1; @@ -458,6 +500,9 @@ c_find_ldoy(int y, double sg, int *rjd, int *ns) { int i, rm, rd; + GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldoy(y), rjd, ns); + + /* Keep existing loop for Julian/reform period */ for (i = 0; i < 30; i++) if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns)) return 1; @@ -465,6 +510,7 @@ c_find_ldoy(int y, double sg, int *rjd, int *ns) } #ifndef NDEBUG +/* :nodoc: */ static int c_find_fdom(int y, int m, double sg, int *rjd, int *ns) { @@ -482,6 +528,9 @@ c_find_ldom(int y, int m, double sg, int *rjd, int *ns) { int i, rm, rd; + GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldom_jd(y, m), rjd, ns); + + /* Keep existing loop for Julian/reform period */ for (i = 0; i < 30; i++) if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns)) return 1; @@ -491,55 +540,69 @@ c_find_ldom(int y, int m, double sg, int *rjd, int *ns) static void c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns) { - double a, b, jd; + int jd; + + GREGORIAN_JD_FAST_PATH(sg, c_gregorian_civil_to_jd(y, m, d), rjd, ns); + + /* Calculate Gregorian JD using optimized algorithm */ + jd = c_gregorian_civil_to_jd(y, m, d); - if (m <= 2) { - y -= 1; - m += 12; - } - a = floor(y / 100.0); - b = 2 - a + floor(a / 4.0); - jd = floor(365.25 * (y + 4716)) + - floor(30.6001 * (m + 1)) + - d + b - 1524; if (jd < sg) { - jd -= b; + /* Before Gregorian switchover - use Julian calendar */ + int y2 = y, m2 = m; + if (m2 <= 2) { + y2 -= 1; + m2 += 12; + } + jd = (int)(floor(365.25 * (y2 + 4716)) + + floor(30.6001 * (m2 + 1)) + + d - 1524); *ns = 0; } - else + else { *ns = 1; + } - *rjd = (int)jd; + *rjd = jd; } static void c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom) { - double x, a, b, c, d, e, y, m, dom; - - if (jd < sg) - a = jd; - else { - x = floor((jd - 1867216.25) / 36524.25); - a = jd + 1 + x - floor(x / 4.0); - } - b = a + 1524; - c = floor((b - 122.1) / 365.25); - d = floor(365.25 * c); - e = floor((b - d) / 30.6001); - dom = b - d - floor(30.6001 * e); - if (e <= 13) { - m = e - 1; - y = c - 4716; - } - else { - m = e - 13; - y = c - 4715; + /* Fast path: pure Gregorian or date after switchover, within safe range */ + if ((c_gregorian_only_p(sg) || jd >= sg) && ns_jd_in_range(jd)) { + c_gregorian_jd_to_civil(jd, ry, rm, rdom); + return; } - *ry = (int)y; - *rm = (int)m; - *rdom = (int)dom; + /* Original algorithm for Julian calendar or extreme dates */ + { + double x, a, b, c, d, e, y, m, dom; + + if (jd < sg) + a = jd; + else { + x = floor((jd - 1867216.25) / 36524.25); + a = jd + 1 + x - floor(x / 4.0); + } + b = a + 1524; + c = floor((b - 122.1) / 365.25); + d = floor(365.25 * c); + e = floor((b - d) / 30.6001); + dom = b - d - floor(30.6001 * e); + if (e <= 13) { + m = e - 1; + y = c - 4716; + } + else { + m = e - 13; + y = c - 4715; + } + + *ry = (int)y; + *rm = (int)m; + *rdom = (int)dom; + } } static void @@ -621,6 +684,7 @@ c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd) } #ifndef NDEBUG +/* :nodoc: */ static void c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns) { @@ -646,6 +710,7 @@ c_jd_to_wday(int jd) } #ifndef NDEBUG +/* :nodoc: */ static void c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk) { @@ -712,6 +777,147 @@ c_gregorian_last_day_of_month(int y, int m) return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m]; } +/* + * Neri-Schneider algorithm for optimized Gregorian date conversion. + * Reference: Neri & Schneider, "Euclidean Affine Functions and Applications + * to Calendar Algorithms", Software: Practice and Experience, 2023. + * https://arxiv.org/abs/2102.06959 + * + * This algorithm provides ~2-3x speedup over traditional floating-point + * implementations by using pure integer arithmetic with multiplication + * and bit-shifts instead of expensive division operations. + */ + +/* JDN of March 1, Year 0 in proleptic Gregorian calendar */ +#define NS_EPOCH 1721120 + +/* Days in a 4-year cycle (3 normal years + 1 leap year) */ +#define NS_DAYS_IN_4_YEARS 1461 + +/* Days in a 400-year Gregorian cycle (97 leap years in 400 years) */ +#define NS_DAYS_IN_400_YEARS 146097 + +/* Years per century */ +#define NS_YEARS_PER_CENTURY 100 + +/* + * Multiplier for extracting year within century using fixed-point arithmetic. + * This is ceil(2^32 / NS_DAYS_IN_4_YEARS) for the Euclidean affine function. + */ +#define NS_YEAR_MULTIPLIER 2939745 + +/* + * Coefficients for month calculation from day-of-year. + * Maps day-of-year to month using: month = (NS_MONTH_COEFF * doy + NS_MONTH_OFFSET) >> 16 + */ +#define NS_MONTH_COEFF 2141 +#define NS_MONTH_OFFSET 197913 + +/* + * Coefficients for civil date to JDN month contribution. + * Maps month to accumulated days: days = (NS_CIVIL_MONTH_COEFF * m - NS_CIVIL_MONTH_OFFSET) / 32 + */ +#define NS_CIVIL_MONTH_COEFF 979 +#define NS_CIVIL_MONTH_OFFSET 2919 +#define NS_CIVIL_MONTH_DIVISOR 32 + +/* Days from March 1 to December 31 (for Jan/Feb year adjustment) */ +#define NS_DAYS_BEFORE_NEW_YEAR 306 + +/* + * Safe bounds for Neri-Schneider algorithm to avoid integer overflow. + * These correspond to approximately years -1,000,000 to +1,000,000. + */ +#define NS_JD_MIN -364000000 +#define NS_JD_MAX 538000000 + +inline static int +ns_jd_in_range(int jd) +{ + return jd >= NS_JD_MIN && jd <= NS_JD_MAX; +} + +/* Optimized: Gregorian date -> Julian Day Number */ +static int +c_gregorian_civil_to_jd(int y, int m, int d) +{ + /* Shift epoch to March 1 of year 0 (Jan/Feb belong to previous year) */ + int j = (m < 3) ? 1 : 0; + int y0 = y - j; + int m0 = j ? m + 12 : m; + int d0 = d - 1; + + /* Calculate year contribution with leap year correction */ + int q1 = DIV(y0, NS_YEARS_PER_CENTURY); + int yc = DIV(NS_DAYS_IN_4_YEARS * y0, 4) - q1 + DIV(q1, 4); + + /* Calculate month contribution using integer arithmetic */ + int mc = (NS_CIVIL_MONTH_COEFF * m0 - NS_CIVIL_MONTH_OFFSET) / NS_CIVIL_MONTH_DIVISOR; + + /* Combine and add epoch offset to get JDN */ + return yc + mc + d0 + NS_EPOCH; +} + +/* Optimized: Julian Day Number -> Gregorian date */ +static void +c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd) +{ + int r0, n1, q1, r1, n2, q2, r2, n3, q3, r3, y0, j; + uint64_t u2; + + /* Convert JDN to rata die (March 1, Year 0 epoch) */ + r0 = jd - NS_EPOCH; + + /* Extract century and day within 400-year cycle */ + /* Use Euclidean (floor) division for negative values */ + n1 = 4 * r0 + 3; + q1 = DIV(n1, NS_DAYS_IN_400_YEARS); + r1 = MOD(n1, NS_DAYS_IN_400_YEARS) / 4; + + /* Calculate year within century and day of year */ + n2 = 4 * r1 + 3; + /* Use 64-bit arithmetic to avoid overflow */ + u2 = (uint64_t)NS_YEAR_MULTIPLIER * (uint64_t)n2; + q2 = (int)(u2 >> 32); + r2 = (int)((uint32_t)u2 / NS_YEAR_MULTIPLIER / 4); + + /* Calculate month and day using integer arithmetic */ + n3 = NS_MONTH_COEFF * r2 + NS_MONTH_OFFSET; + q3 = n3 >> 16; + r3 = (n3 & 0xFFFF) / NS_MONTH_COEFF; + + /* Combine century and year */ + y0 = NS_YEARS_PER_CENTURY * q1 + q2; + + /* Adjust for January/February (shift from fiscal year) */ + j = (r2 >= NS_DAYS_BEFORE_NEW_YEAR) ? 1 : 0; + + *ry = y0 + j; + *rm = j ? q3 - 12 : q3; + *rd = r3 + 1; +} + +/* O(1) first day of year for Gregorian calendar */ +inline static int +c_gregorian_fdoy(int y) +{ + return c_gregorian_civil_to_jd(y, 1, 1); +} + +/* O(1) last day of year for Gregorian calendar */ +inline static int +c_gregorian_ldoy(int y) +{ + return c_gregorian_civil_to_jd(y, 12, 31); +} + +/* O(1) last day of month (JDN) for Gregorian calendar */ +inline static int +c_gregorian_ldom_jd(int y, int m) +{ + return c_gregorian_civil_to_jd(y, m, c_gregorian_last_day_of_month(y, m)); +} + static int c_valid_julian_p(int y, int m, int d, int *rm, int *rd) { @@ -758,6 +964,8 @@ c_valid_civil_p(int y, int m, int d, double sg, if (m < 0) m += 13; + if (m < 1 || m > 12) + return 0; if (d < 0) { if (!c_find_ldom(y, m, sg, rjd, ns)) return 0; @@ -822,6 +1030,7 @@ c_valid_weeknum_p(int y, int w, int d, int f, double sg, } #ifndef NDEBUG +/* :nodoc: */ static int c_valid_nth_kday_p(int y, int m, int n, int k, double sg, int *rm, int *rn, int *rk, int *rjd, int *ns) @@ -963,6 +1172,7 @@ ns_to_day(VALUE n) } #ifndef NDEBUG +/* :nodoc: */ static VALUE ms_to_sec(VALUE m) { @@ -981,6 +1191,7 @@ ns_to_sec(VALUE n) } #ifndef NDEBUG +/* :nodoc: */ inline static VALUE ins_to_day(int n) { @@ -1016,6 +1227,7 @@ day_to_sec(VALUE d) } #ifndef NDEBUG +/* :nodoc: */ static VALUE day_to_ns(VALUE d) { @@ -1040,6 +1252,7 @@ sec_to_ns(VALUE s) } #ifndef NDEBUG +/* :nodoc: */ static VALUE isec_to_ns(int s) { @@ -1066,6 +1279,7 @@ div_df(VALUE d, VALUE *f) } #ifndef NDEBUG +/* :nodoc: */ static VALUE div_sf(VALUE s, VALUE *f) { @@ -1500,6 +1714,7 @@ m_df(union DateData *x) } #ifndef NDEBUG +/* :nodoc: */ static VALUE m_df_in_day(union DateData *x) { @@ -1577,7 +1792,7 @@ m_ajd(union DateData *x) if (simple_dat_p(x)) { r = m_real_jd(x); - if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) { + if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2) && FIX2LONG(r) >= (FIXNUM_MIN + 1) / 2) { long ir = FIX2LONG(r); ir = ir * 2 - 1; return rb_rational_new2(LONG2FIX(ir), INT2FIX(2)); @@ -1997,6 +2212,7 @@ expect_numeric(VALUE x) } #ifndef NDEBUG +/* :nodoc: */ static void civil_to_jd(VALUE y, int m, int d, double sg, VALUE *nth, int *ry, @@ -2309,6 +2525,7 @@ valid_weeknum_p(VALUE y, int w, int d, int f, double sg, } #ifndef NDEBUG +/* :nodoc: */ static int valid_nth_kday_p(VALUE y, int m, int n, int k, double sg, VALUE *nth, int *ry, @@ -2446,6 +2663,7 @@ valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd) } #ifndef NDEBUG +/* :nodoc: */ static VALUE date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass) { @@ -2466,13 +2684,16 @@ date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.valid_jd?(jd[, start=Date::ITALY]) -> bool + * Date.valid_jd?(jd, start = Date::ITALY) -> true * - * Just returns true. It's nonsense, but is for symmetry. + * Implemented for compatibility; + * returns +true+ unless +jd+ is invalid (i.e., not a Numeric). * - * Date.valid_jd?(2451944) #=> true + * Date.valid_jd?(2451944) # => true * - * See also ::jd. + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * Related: Date.jd. */ static VALUE date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass) @@ -2532,6 +2753,7 @@ valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd) } #ifndef NDEBUG +/* :nodoc: */ static VALUE date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass) { @@ -2554,18 +2776,18 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.valid_civil?(year, month, mday[, start=Date::ITALY]) -> bool - * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool + * Date.valid_civil?(year, month, mday, start = Date::ITALY) -> true or false * - * Returns true if the given calendar date is valid, and false if not. - * Valid in this context is whether the arguments passed to this - * method would be accepted by ::new. + * Returns +true+ if the arguments define a valid ordinal date, + * +false+ otherwise: * - * Date.valid_date?(2001,2,3) #=> true - * Date.valid_date?(2001,2,29) #=> false - * Date.valid_date?(2001,2,-1) #=> true + * Date.valid_date?(2001, 2, 3) # => true + * Date.valid_date?(2001, 2, 29) # => false + * Date.valid_date?(2001, 2, -1) # => true * - * See also ::jd and ::civil. + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * Related: Date.jd, Date.new. */ static VALUE date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass) @@ -2621,6 +2843,7 @@ valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd) } #ifndef NDEBUG +/* :nodoc: */ static VALUE date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass) { @@ -2642,14 +2865,17 @@ date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.valid_ordinal?(year, yday[, start=Date::ITALY]) -> bool + * Date.valid_ordinal?(year, yday, start = Date::ITALY) -> true or false * - * Returns true if the given ordinal date is valid, and false if not. + * Returns +true+ if the arguments define a valid ordinal date, + * +false+ otherwise: * - * Date.valid_ordinal?(2001,34) #=> true - * Date.valid_ordinal?(2001,366) #=> false + * Date.valid_ordinal?(2001, 34) # => true + * Date.valid_ordinal?(2001, 366) # => false * - * See also ::jd and ::ordinal. + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * Related: Date.jd, Date.ordinal. */ static VALUE date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass) @@ -2704,6 +2930,7 @@ valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd) } #ifndef NDEBUG +/* :nodoc: */ static VALUE date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass) { @@ -2726,14 +2953,19 @@ date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.valid_commercial?(cwyear, cweek, cwday[, start=Date::ITALY]) -> bool + * Date.valid_commercial?(cwyear, cweek, cwday, start = Date::ITALY) -> true or false + * + * Returns +true+ if the arguments define a valid commercial date, + * +false+ otherwise: + * + * Date.valid_commercial?(2001, 5, 6) # => true + * Date.valid_commercial?(2001, 5, 8) # => false * - * Returns true if the given week date is valid, and false if not. + * See Date.commercial. * - * Date.valid_commercial?(2001,5,6) #=> true - * Date.valid_commercial?(2001,5,8) #=> false + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. * - * See also ::jd and ::commercial. + * Related: Date.jd, Date.commercial. */ static VALUE date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass) @@ -2760,6 +2992,7 @@ date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass) } #ifndef NDEBUG +/* :nodoc: */ static VALUE valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd) { @@ -2791,6 +3024,7 @@ valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd) } } +/* :nodoc: */ static VALUE date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass) { @@ -2811,6 +3045,7 @@ date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass) return valid_weeknum_sub(5, argv2, klass, 1); } +/* :nodoc: */ static VALUE date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass) { @@ -2862,6 +3097,7 @@ valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd) } } +/* :nodoc: */ static VALUE date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) { @@ -2882,6 +3118,7 @@ date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) return valid_nth_kday_sub(5, argv2, klass, 1); } +/* :nodoc: */ static VALUE date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) { @@ -2904,6 +3141,7 @@ date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass) return Qtrue; } +/* :nodoc: */ static VALUE date_s_zone_to_diff(VALUE klass, VALUE str) { @@ -2913,13 +3151,15 @@ date_s_zone_to_diff(VALUE klass, VALUE str) /* * call-seq: - * Date.julian_leap?(year) -> bool + * Date.julian_leap?(year) -> true or false + * + * Returns +true+ if the given year is a leap year + * in the {proleptic Julian calendar}[https://en.wikipedia.org/wiki/Proleptic_Julian_calendar], +false+ otherwise: * - * Returns true if the given year is a leap year of the proleptic - * Julian calendar. + * Date.julian_leap?(1900) # => true + * Date.julian_leap?(1901) # => false * - * Date.julian_leap?(1900) #=> true - * Date.julian_leap?(1901) #=> false + * Related: Date.gregorian_leap?. */ static VALUE date_s_julian_leap_p(VALUE klass, VALUE y) @@ -2934,14 +3174,15 @@ date_s_julian_leap_p(VALUE klass, VALUE y) /* * call-seq: - * Date.gregorian_leap?(year) -> bool - * Date.leap?(year) -> bool + * Date.gregorian_leap?(year) -> true or false * - * Returns true if the given year is a leap year of the proleptic - * Gregorian calendar. + * Returns +true+ if the given year is a leap year + * in the {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar], +false+ otherwise: * - * Date.gregorian_leap?(1900) #=> false - * Date.gregorian_leap?(2000) #=> true + * Date.gregorian_leap?(2000) # => true + * Date.gregorian_leap?(2001) # => false + * + * Related: Date.julian_leap?. */ static VALUE date_s_gregorian_leap_p(VALUE klass, VALUE y) @@ -3094,6 +3335,7 @@ old_to_new(VALUE ajd, VALUE of, VALUE sg, } #ifndef NDEBUG +/* :nodoc: */ static VALUE date_s_new_bang(int argc, VALUE *argv, VALUE klass) { @@ -3281,16 +3523,29 @@ static VALUE d_lite_plus(VALUE, VALUE); /* * call-seq: - * Date.jd([jd=0[, start=Date::ITALY]]) -> date + * Date.jd(jd = 0, start = Date::ITALY) -> date + * + * Returns a new \Date object formed from the arguments: + * + * Date.jd(2451944).to_s # => "2001-02-03" + * Date.jd(2451945).to_s # => "2001-02-04" + * Date.jd(0).to_s # => "-4712-01-01" + * + * The returned date is: + * + * - Gregorian, if the argument is greater than or equal to +start+: + * + * Date::ITALY # => 2299161 + * Date.jd(Date::ITALY).gregorian? # => true + * Date.jd(Date::ITALY + 1).gregorian? # => true + * + * - Julian, otherwise * - * Creates a date object denoting the given chronological Julian day - * number. + * Date.jd(Date::ITALY - 1).julian? # => true * - * Date.jd(2451944) #=> #<Date: 2001-02-03 ...> - * Date.jd(2451945) #=> #<Date: 2001-02-04 ...> - * Date.jd(0) #=> #<Date: -4712-01-01 ...> + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. * - * See also ::new. + * Related: Date.new. */ static VALUE date_s_jd(int argc, VALUE *argv, VALUE klass) @@ -3329,19 +3584,33 @@ date_s_jd(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.ordinal([year=-4712[, yday=1[, start=Date::ITALY]]]) -> date + * Date.ordinal(year = -4712, yday = 1, start = Date::ITALY) -> date + * + * Returns a new \Date object formed fom the arguments. + * + * With no arguments, returns the date for January 1, -4712: + * + * Date.ordinal.to_s # => "-4712-01-01" + * + * With argument +year+, returns the date for January 1 of that year: + * + * Date.ordinal(2001).to_s # => "2001-01-01" + * Date.ordinal(-2001).to_s # => "-2001-01-01" + * + * With positive argument +yday+ == +n+, + * returns the date for the +nth+ day of the given year: + * + * Date.ordinal(2001, 14).to_s # => "2001-01-14" * - * Creates a date object denoting the given ordinal date. + * With negative argument +yday+, counts backward from the end of the year: * - * The day of year should be a negative or a positive number (as a - * relative day from the end of year when negative). It should not be - * zero. + * Date.ordinal(2001, -14).to_s # => "2001-12-18" * - * Date.ordinal(2001) #=> #<Date: 2001-01-01 ...> - * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...> - * Date.ordinal(2001,-1) #=> #<Date: 2001-12-31 ...> + * Raises an exception if +yday+ is zero or out of range. * - * See also ::jd and ::new. + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * Related: Date.jd, Date.new. */ static VALUE date_s_ordinal(int argc, VALUE *argv, VALUE klass) @@ -3389,29 +3658,7 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass) } /* - * call-seq: - * Date.civil([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date - * Date.new([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date - * - * Creates a date object denoting the given calendar date. - * - * In this class, BCE years are counted astronomically. Thus, the - * year before the year 1 is the year zero, and the year preceding the - * year zero is the year -1. The month and the day of month should be - * a negative or a positive number (as a relative month/day from the - * end of year/month when negative). They should not be zero. - * - * The last argument should be a Julian day number which denotes the - * day of calendar reform. Date::ITALY (2299161=1582-10-15), - * Date::ENGLAND (2361222=1752-09-14), Date::GREGORIAN (the proleptic - * Gregorian calendar) and Date::JULIAN (the proleptic Julian - * calendar) can be specified as a day of calendar reform. - * - * Date.new(2001) #=> #<Date: 2001-01-01 ...> - * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...> - * Date.new(2001,2,-1) #=> #<Date: 2001-02-28 ...> - * - * See also ::jd. + * Same as Date.new. */ static VALUE date_s_civil(int argc, VALUE *argv, VALUE klass) @@ -3419,6 +3666,29 @@ date_s_civil(int argc, VALUE *argv, VALUE klass) return date_initialize(argc, argv, d_lite_s_alloc_simple(klass)); } +/* + * call-seq: + * Date.new(year = -4712, month = 1, mday = 1, start = Date::ITALY) -> date + * + * Returns a new \Date object constructed from the given arguments: + * + * Date.new(2022).to_s # => "2022-01-01" + * Date.new(2022, 2).to_s # => "2022-02-01" + * Date.new(2022, 2, 4).to_s # => "2022-02-04" + * + * Argument +month+ should be in range (1..12) or range (-12..-1); + * when the argument is negative, counts backward from the end of the year: + * + * Date.new(2022, -11, 4).to_s # => "2022-02-04" + * + * Argument +mday+ should be in range (1..n) or range (-n..-1) + * where +n+ is the number of days in the month; + * when the argument is negative, counts backward from the end of the month. + * + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * Related: Date.jd. + */ static VALUE date_initialize(int argc, VALUE *argv, VALUE self) { @@ -3483,19 +3753,47 @@ date_initialize(int argc, VALUE *argv, VALUE self) /* * call-seq: - * Date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) -> date + * Date.commercial(cwyear = -4712, cweek = 1, cwday = 1, start = Date::ITALY) -> date + * + * Returns a new \Date object constructed from the arguments. + * + * Argument +cwyear+ gives the year, and should be an integer. + * + * Argument +cweek+ gives the index of the week within the year, + * and should be in range (1..53) or (-53..-1); + * in some years, 53 or -53 will be out-of-range; + * if negative, counts backward from the end of the year: + * + * Date.commercial(2022, 1, 1).to_s # => "2022-01-03" + * Date.commercial(2022, 52, 1).to_s # => "2022-12-26" + * + * Argument +cwday+ gives the indes of the weekday within the week, + * and should be in range (1..7) or (-7..-1); + * 1 or -7 is Monday; + * if negative, counts backward from the end of the week: + * + * Date.commercial(2022, 1, 1).to_s # => "2022-01-03" + * Date.commercial(2022, 1, -7).to_s # => "2022-01-03" * - * Creates a date object denoting the given week date. + * When +cweek+ is 1: * - * The week and the day of week should be a negative or a positive - * number (as a relative week/day from the end of year/week when - * negative). They should not be zero. + * - If January 1 is a Friday, Saturday, or Sunday, + * the first week begins in the week after: * - * Date.commercial(2001) #=> #<Date: 2001-01-01 ...> - * Date.commercial(2002) #=> #<Date: 2001-12-31 ...> - * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...> + * Date::ABBR_DAYNAMES[Date.new(2023, 1, 1).wday] # => "Sun" + * Date.commercial(2023, 1, 1).to_s # => "2023-01-02" + Date.commercial(2023, 1, 7).to_s # => "2023-01-08" * - * See also ::jd and ::new. + * - Otherwise, the first week is the week of January 1, + * which may mean some of the days fall on the year before: + * + * Date::ABBR_DAYNAMES[Date.new(2020, 1, 1).wday] # => "Wed" + * Date.commercial(2020, 1, 1).to_s # => "2019-12-30" + Date.commercial(2020, 1, 7).to_s # => "2020-01-05" + * + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * Related: Date.jd, Date.new, Date.ordinal. */ static VALUE date_s_commercial(int argc, VALUE *argv, VALUE klass) @@ -3547,6 +3845,7 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass) } #ifndef NDEBUG +/* :nodoc: */ static VALUE date_s_weeknum(int argc, VALUE *argv, VALUE klass) { @@ -3596,6 +3895,7 @@ date_s_weeknum(int argc, VALUE *argv, VALUE klass) return ret; } +/* :nodoc: */ static VALUE date_s_nth_kday(int argc, VALUE *argv, VALUE klass) { @@ -3670,11 +3970,14 @@ static void set_sg(union DateData *, double); /* * call-seq: - * Date.today([start=Date::ITALY]) -> date + * Date.today(start = Date::ITALY) -> date + * + * Returns a new \Date object constructed from the present date: + * + * Date.today.to_s # => "2022-07-06" * - * Creates a date object denoting the present day. + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. * - * Date.today #=> #<Date: 2011-06-11 ...> */ static VALUE date_s_today(int argc, VALUE *argv, VALUE klass) @@ -3768,7 +4071,6 @@ static VALUE rt_complete_frags(VALUE klass, VALUE hash) { static VALUE tab = Qnil; - int g; long e; VALUE k, a, d; @@ -3865,9 +4167,13 @@ rt_complete_frags(VALUE klass, VALUE hash) rb_gc_register_mark_object(tab); } + k = a = Qnil; + { - long i, eno = 0, idx = 0; + long i, eno = 0; + VALUE t = Qnil; + e = 0; for (i = 0; i < RARRAY_LEN(tab); i++) { VALUE x, a; @@ -3882,23 +4188,20 @@ rt_complete_frags(VALUE klass, VALUE hash) n++; if (n > eno) { eno = n; - idx = i; + t = x; } } } - if (eno == 0) - g = 0; - else { - g = 1; - k = RARRAY_AREF(RARRAY_AREF(tab, idx), 0); - a = RARRAY_AREF(RARRAY_AREF(tab, idx), 1); - e = eno; + if (eno > 0) { + k = RARRAY_AREF(t, 0); + a = RARRAY_AREF(t, 1); } + e = eno; } d = Qnil; - if (g && !NIL_P(k) && (RARRAY_LEN(a) - e)) { + if (!NIL_P(k) && (RARRAY_LEN(a) > e)) { if (k == sym("ordinal")) { if (NIL_P(ref_hash("year"))) { if (NIL_P(d)) @@ -3985,7 +4288,7 @@ rt_complete_frags(VALUE klass, VALUE hash) } } - if (g && k == sym("time")) { + if (k == sym("time")) { if (f_le_p(klass, cDateTime)) { if (NIL_P(d)) d = date_s_today(0, (VALUE *)0, cDate); @@ -4225,6 +4528,7 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass, rb_scan_args(argc, argv, "11", &vstr, &vfmt); StringValue(vstr); + if (argc > 1) StringValue(vfmt); if (!rb_enc_str_asciicompat_p(vstr)) rb_raise(rb_eArgError, "string should have ASCII compatible encoding"); @@ -4235,7 +4539,6 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass, flen = strlen(default_fmt); } else { - StringValue(vfmt); if (!rb_enc_str_asciicompat_p(vfmt)) rb_raise(rb_eArgError, "format should have ASCII compatible encoding"); @@ -4265,16 +4568,20 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass, /* * call-seq: - * Date._strptime(string[, format='%F']) -> hash + * Date._strptime(string, format = '%F') -> hash * - * Parses the given representation of date and time with the given - * template, and returns a hash of parsed elements. _strptime does - * not support specification of flags and width unlike strftime. + * Returns a hash of values parsed from +string+ + * according to the given +format+: * - * Date._strptime('2001-02-03', '%Y-%m-%d') - * #=> {:year=>2001, :mon=>2, :mday=>3} + * Date._strptime('2001-02-03', '%Y-%m-%d') # => {:year=>2001, :mon=>2, :mday=>3} * - * See also strptime(3) and #strftime. + * For other formats, see + * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]. + * (Unlike Date.strftime, does not support flags and width.) + * + * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html]. + * + * Related: Date.strptime (returns a \Date object). */ static VALUE date_s__strptime(int argc, VALUE *argv, VALUE klass) @@ -4284,21 +4591,28 @@ date_s__strptime(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.strptime([string='-4712-01-01'[, format='%F'[, start=Date::ITALY]]]) -> date + * Date.strptime(string = '-4712-01-01', format = '%F', start = Date::ITALY) -> date * - * Parses the given representation of date and time with the given - * template, and creates a date object. strptime does not support - * specification of flags and width unlike strftime. + * Returns a new \Date object with values parsed from +string+, + * according to the given +format+: * - * Date.strptime('2001-02-03', '%Y-%m-%d') #=> #<Date: 2001-02-03 ...> - * Date.strptime('03-02-2001', '%d-%m-%Y') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001-034', '%Y-%j') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001-W05-6', '%G-W%V-%u') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001 04 6', '%Y %U %w') #=> #<Date: 2001-02-03 ...> - * Date.strptime('2001 05 6', '%Y %W %u') #=> #<Date: 2001-02-03 ...> - * Date.strptime('sat3feb01', '%a%d%b%y') #=> #<Date: 2001-02-03 ...> + * Date.strptime('2001-02-03', '%Y-%m-%d') # => #<Date: 2001-02-03> + * Date.strptime('03-02-2001', '%d-%m-%Y') # => #<Date: 2001-02-03> + * Date.strptime('2001-034', '%Y-%j') # => #<Date: 2001-02-03> + * Date.strptime('2001-W05-6', '%G-W%V-%u') # => #<Date: 2001-02-03> + * Date.strptime('2001 04 6', '%Y %U %w') # => #<Date: 2001-02-03> + * Date.strptime('2001 05 6', '%Y %W %u') # => #<Date: 2001-02-03> + * Date.strptime('sat3feb01', '%a%d%b%y') # => #<Date: 2001-02-03> * - * See also strptime(3) and #strftime. + * For other formats, see + * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]. + * (Unlike Date.strftime, does not support flags and width.) + * + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * + * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html]. + * + * Related: Date._strptime (returns a hash). */ static VALUE date_s_strptime(int argc, VALUE *argv, VALUE klass) @@ -4309,7 +4623,7 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass) switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: fmt = rb_str_new2("%F"); case 2: @@ -4328,13 +4642,42 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass) VALUE date__parse(VALUE str, VALUE comp); +static size_t +get_limit(VALUE opt) +{ + if (!NIL_P(opt)) { + VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit"))); + if (NIL_P(limit)) return SIZE_MAX; + return NUM2SIZET(limit); + } + return 128; +} + +#ifndef HAVE_RB_CATEGORY_WARN +#define rb_category_warn(category, fmt) rb_warn(fmt) +#endif + +static VALUE +check_limit(VALUE str, VALUE opt) +{ + size_t slen, limit; + StringValue(str); + slen = RSTRING_LEN(str); + limit = get_limit(opt); + if (slen > limit) { + rb_raise(rb_eArgError, + "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit); + } + return str; +} + static VALUE date_s__parse_internal(int argc, VALUE *argv, VALUE klass) { - VALUE vstr, vcomp, hash; + VALUE vstr, vcomp, hash, opt; - rb_scan_args(argc, argv, "11", &vstr, &vcomp); - StringValue(vstr); + argc = rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt); + vstr = check_limit(vstr, opt); if (!rb_enc_str_asciicompat_p(vstr)) rb_raise(rb_eArgError, "string should have ASCII compatible encoding"); @@ -4348,21 +4691,32 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date._parse(string[, comp=true]) -> hash + * Date._parse(string, comp = true, limit: 128) -> hash * - * Parses the given representation of date and time, and returns a - * hash of parsed elements. + * <b>Note</b>: + * This method recognizes many forms in +string+, + * but it is not a validator. + * For formats, see + * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings] * - * This method **does not** function as a validator. If the input - * string does not match valid formats strictly, you may get a cryptic - * result. Should consider to use `Date._strptime` or - * `DateTime._strptime` instead of this method as possible. + * If +string+ does not specify a valid date, + * the result is unpredictable; + * consider using Date._strptime instead. * - * If the optional second argument is true and the detected year is in - * the range "00" to "99", considers the year a 2-digit form and makes - * it full. + * Returns a hash of values parsed from +string+: + * + * Date._parse('2001-02-03') # => {:year=>2001, :mon=>2, :mday=>3} + * + * If +comp+ is +true+ and the given year is in the range <tt>(0..99)</tt>, + * the current century is supplied; + * otherwise, the year is taken as given: * - * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3} + * Date._parse('01-02-03', true) # => {:year=>2001, :mon=>2, :mday=>3} + * Date._parse('01-02-03', false) # => {:year=>1, :mon=>2, :mday=>3} + * + * See argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date.parse(returns a \Date object). */ static VALUE date_s__parse(int argc, VALUE *argv, VALUE klass) @@ -4372,34 +4726,47 @@ date_s__parse(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date + * Date.parse(string = '-4712-01-01', comp = true, start = Date::ITALY, limit: 128) -> date * - * Parses the given representation of date and time, and creates a - * date object. + * <b>Note</b>: + * This method recognizes many forms in +string+, + * but it is not a validator. + * For formats, see + * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings] + * If +string+ does not specify a valid date, + * the result is unpredictable; + * consider using Date._strptime instead. * - * This method **does not** function as a validator. If the input - * string does not match valid formats strictly, you may get a cryptic - * result. Should consider to use `Date.strptime` instead of this - * method as possible. + * Returns a new \Date object with values parsed from +string+: * - * If the optional second argument is true and the detected year is in - * the range "00" to "99", considers the year a 2-digit form and makes - * it full. + * Date.parse('2001-02-03') # => #<Date: 2001-02-03> + * Date.parse('20010203') # => #<Date: 2001-02-03> + * Date.parse('3rd Feb 2001') # => #<Date: 2001-02-03> + * + * If +comp+ is +true+ and the given year is in the range <tt>(0..99)</tt>, + * the current century is supplied; + * otherwise, the year is taken as given: + * + * Date.parse('01-02-03', true) # => #<Date: 2001-02-03> + * Date.parse('01-02-03', false) # => #<Date: 0001-02-03> * - * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...> - * Date.parse('20010203') #=> #<Date: 2001-02-03 ...> - * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...> + * See: + * + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date._parse (returns a hash). */ static VALUE date_s_parse(int argc, VALUE *argv, VALUE klass) { - VALUE str, comp, sg; + VALUE str, comp, sg, opt; - rb_scan_args(argc, argv, "03", &str, &comp, &sg); + argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: comp = Qtrue; case 2: @@ -4407,11 +4774,12 @@ date_s_parse(int argc, VALUE *argv, VALUE klass) } { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = comp; - hash = date_s__parse(2, argv2, klass); + int argc2 = 2; + VALUE argv2[3], hash; + argv2[0] = str; + argv2[1] = comp; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__parse(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } @@ -4425,256 +4793,417 @@ VALUE date__jisx0301(VALUE); /* * call-seq: - * Date._iso8601(string) -> hash + * Date._iso8601(string, limit: 128) -> hash + * + * Returns a hash of values parsed from +string+, which should contain + * an {ISO 8601 formatted date}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]: + * + * d = Date.new(2001, 2, 3) + * s = d.iso8601 # => "2001-02-03" + * Date._iso8601(s) # => {:mday=>3, :year=>2001, :mon=>2} * - * Returns a hash of parsed elements. + * See argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date.iso8601 (returns a \Date object). */ static VALUE -date_s__iso8601(VALUE klass, VALUE str) +date_s__iso8601(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(str)) str = check_limit(str, opt); + return date__iso8601(str); } /* * call-seq: - * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY]) -> date + * Date.iso8601(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date * - * Creates a new Date object by parsing from a string according to - * some typical ISO 8601 formats. + * Returns a new \Date object with values parsed from +string+, + * which should contain + * an {ISO 8601 formatted date}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]: * - * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...> - * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...> - * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...> + * d = Date.new(2001, 2, 3) + * s = d.iso8601 # => "2001-02-03" + * Date.iso8601(s) # => #<Date: 2001-02-03> + * + * See: + * + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date._iso8601 (returns a hash). */ static VALUE date_s_iso8601(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__iso8601(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__iso8601(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._rfc3339(string) -> hash + * Date._rfc3339(string, limit: 128) -> hash + * + * Returns a hash of values parsed from +string+, which should be a valid + * {RFC 3339 format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+3339+Format]: * - * Returns a hash of parsed elements. + * d = Date.new(2001, 2, 3) + * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00" + * Date._rfc3339(s) + * # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0} + * + * See argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date.rfc3339 (returns a \Date object). */ static VALUE -date_s__rfc3339(VALUE klass, VALUE str) +date_s__rfc3339(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(str)) str = check_limit(str, opt); + return date__rfc3339(str); } /* * call-seq: - * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> date + * Date.rfc3339(string = '-4712-01-01T00:00:00+00:00', start = Date::ITALY, limit: 128) -> date * - * Creates a new Date object by parsing from a string according to - * some typical RFC 3339 formats. + * Returns a new \Date object with values parsed from +string+, + * which should be a valid + * {RFC 3339 format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+3339+Format]: + * + * d = Date.new(2001, 2, 3) + * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00" + * Date.rfc3339(s) # => #<Date: 2001-02-03> + * + * See: * - * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...> + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date._rfc3339 (returns a hash). */ static VALUE date_s_rfc3339(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__rfc3339(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__rfc3339(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._xmlschema(string) -> hash + * Date._xmlschema(string, limit: 128) -> hash + * + * Returns a hash of values parsed from +string+, which should be a valid + * XML date format: + * + * d = Date.new(2001, 2, 3) + * s = d.xmlschema # => "2001-02-03" + * Date._xmlschema(s) # => {:year=>2001, :mon=>2, :mday=>3} + * + * See argument {limit}[rdoc-ref:Date@Argument+limit]. * - * Returns a hash of parsed elements. + * Related: Date.xmlschema (returns a \Date object). */ static VALUE -date_s__xmlschema(VALUE klass, VALUE str) +date_s__xmlschema(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(str)) str = check_limit(str, opt); + return date__xmlschema(str); } /* * call-seq: - * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY]) -> date + * Date.xmlschema(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date * - * Creates a new Date object by parsing from a string according to - * some typical XML Schema formats. + * Returns a new \Date object with values parsed from +string+, + * which should be a valid XML date format: + * + * d = Date.new(2001, 2, 3) + * s = d.xmlschema # => "2001-02-03" + * Date.xmlschema(s) # => #<Date: 2001-02-03> * - * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...> + * See: + * + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date._xmlschema (returns a hash). */ static VALUE date_s_xmlschema(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__xmlschema(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__xmlschema(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._rfc2822(string) -> hash - * Date._rfc822(string) -> hash + * Date._rfc2822(string, limit: 128) -> hash + * + * Returns a hash of values parsed from +string+, which should be a valid + * {RFC 2822 date format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+2822+Format]: * - * Returns a hash of parsed elements. + * d = Date.new(2001, 2, 3) + * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000" + * Date._rfc2822(s) + * # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0} + * + * See argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date.rfc2822 (returns a \Date object). */ static VALUE -date_s__rfc2822(VALUE klass, VALUE str) +date_s__rfc2822(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(str)) str = check_limit(str, opt); + return date__rfc2822(str); } /* * call-seq: - * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date - * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date + * Date.rfc2822(string = 'Mon, 1 Jan -4712 00:00:00 +0000', start = Date::ITALY, limit: 128) -> date * - * Creates a new Date object by parsing from a string according to - * some typical RFC 2822 formats. + * Returns a new \Date object with values parsed from +string+, + * which should be a valid + * {RFC 2822 date format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+2822+Format]: + * + * d = Date.new(2001, 2, 3) + * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000" + * Date.rfc2822(s) # => #<Date: 2001-02-03> + * + * See: + * + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * - * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000') - * #=> #<Date: 2001-02-03 ...> + * Related: Date._rfc2822 (returns a hash). */ static VALUE date_s_rfc2822(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__rfc2822(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__rfc2822(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._httpdate(string) -> hash + * Date._httpdate(string, limit: 128) -> hash * - * Returns a hash of parsed elements. + * Returns a hash of values parsed from +string+, which should be a valid + * {HTTP date format}[rdoc-ref:language/strftime_formatting.rdoc@HTTP+Format]: + * + * d = Date.new(2001, 2, 3) + * s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT" + * Date._httpdate(s) + * # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0} + * + * Related: Date.httpdate (returns a \Date object). */ static VALUE -date_s__httpdate(VALUE klass, VALUE str) +date_s__httpdate(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(str)) str = check_limit(str, opt); + return date__httpdate(str); } /* * call-seq: - * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> date + * Date.httpdate(string = 'Mon, 01 Jan -4712 00:00:00 GMT', start = Date::ITALY, limit: 128) -> date * - * Creates a new Date object by parsing from a string according to - * some RFC 2616 format. + * Returns a new \Date object with values parsed from +string+, + * which should be a valid + * {HTTP date format}[rdoc-ref:language/strftime_formatting.rdoc@HTTP+Format]: + * + * d = Date.new(2001, 2, 3) + s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT" + Date.httpdate(s) # => #<Date: 2001-02-03> + * + * See: * - * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT') - * #=> #<Date: 2001-02-03 ...> + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date._httpdate (returns a hash). */ static VALUE date_s_httpdate(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__httpdate(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__httpdate(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } /* * call-seq: - * Date._jisx0301(string) -> hash + * Date._jisx0301(string, limit: 128) -> hash + * + * Returns a hash of values parsed from +string+, which should be a valid + * {JIS X 0301 date format}[rdoc-ref:language/strftime_formatting.rdoc@JIS+X+0301+Format]: + * + * d = Date.new(2001, 2, 3) + * s = d.jisx0301 # => "H13.02.03" + * Date._jisx0301(s) # => {:year=>2001, :mon=>2, :mday=>3} + * + * See argument {limit}[rdoc-ref:Date@Argument+limit]. * - * Returns a hash of parsed elements. + * Related: Date.jisx0301 (returns a \Date object). */ static VALUE -date_s__jisx0301(VALUE klass, VALUE str) +date_s__jisx0301(int argc, VALUE *argv, VALUE klass) { + VALUE str, opt; + + rb_scan_args(argc, argv, "1:", &str, &opt); + if (!NIL_P(str)) str = check_limit(str, opt); + return date__jisx0301(str); } /* * call-seq: - * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY]) -> date + * Date.jisx0301(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date * - * Creates a new Date object by parsing from a string according to - * some typical JIS X 0301 formats. + * Returns a new \Date object with values parsed from +string+, + * which should be a valid {JIS X 0301 format}[rdoc-ref:language/strftime_formatting.rdoc@JIS+X+0301+Format]: * - * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...> + * d = Date.new(2001, 2, 3) + * s = d.jisx0301 # => "H13.02.03" + * Date.jisx0301(s) # => #<Date: 2001-02-03> * * For no-era year, legacy format, Heisei is assumed. * - * Date.jisx0301('13.02.03') #=> #<Date: 2001-02-03 ...> + * Date.jisx0301('13.02.03') # => #<Date: 2001-02-03> + * + * See: + * + * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. + * - Argument {limit}[rdoc-ref:Date@Argument+limit]. + * + * Related: Date._jisx0301 (returns a hash). */ static VALUE date_s_jisx0301(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__jisx0301(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + if (!NIL_P(opt)) argv2[argc2++] = opt; + hash = date_s__jisx0301(argc2, argv2, klass); return d_new_by_frags(klass, hash, sg); } } @@ -4844,6 +5373,7 @@ d_lite_initialize_copy(VALUE copy, VALUE date) } #ifndef NDEBUG +/* :nodoc: */ static VALUE d_lite_fill(VALUE self) { @@ -4933,12 +5463,15 @@ d_lite_mjd(VALUE self) /* * call-seq: - * d.ld -> integer + * ld -> integer * - * Returns the Lilian day number. This is a whole number, which is - * adjusted by the offset as the local time. + * Returns the + * {Lilian day number}[https://en.wikipedia.org/wiki/Lilian_date], + * which is the number of days since the beginning of the Gregorian + * calendar, October 15, 1582. + * + * Date.new(2001, 2, 3).ld # => 152784 * - * Date.new(2001,2,3).ld #=> 152784 */ static VALUE d_lite_ld(VALUE self) @@ -4949,12 +5482,13 @@ d_lite_ld(VALUE self) /* * call-seq: - * d.year -> integer + * year -> integer + * + * Returns the year: * - * Returns the year. + * Date.new(2001, 2, 3).year # => 2001 + * (Date.new(1, 1, 1) - 1).year # => 0 * - * Date.new(2001,2,3).year #=> 2001 - * (Date.new(1,1,1) - 1).year #=> 0 */ static VALUE d_lite_year(VALUE self) @@ -4965,11 +5499,12 @@ d_lite_year(VALUE self) /* * call-seq: - * d.yday -> fixnum + * yday -> integer + * + * Returns the day of the year, in range (1..366): * - * Returns the day of the year (1-366). + * Date.new(2001, 2, 3).yday # => 34 * - * Date.new(2001,2,3).yday #=> 34 */ static VALUE d_lite_yday(VALUE self) @@ -4980,12 +5515,12 @@ d_lite_yday(VALUE self) /* * call-seq: - * d.mon -> fixnum - * d.month -> fixnum + * mon -> integer * - * Returns the month (1-12). + * Returns the month in range (1..12): + * + * Date.new(2001, 2, 3).mon # => 2 * - * Date.new(2001,2,3).mon #=> 2 */ static VALUE d_lite_mon(VALUE self) @@ -4996,12 +5531,12 @@ d_lite_mon(VALUE self) /* * call-seq: - * d.mday -> fixnum - * d.day -> fixnum + * mday -> integer + * + * Returns the day of the month in range (1..31): * - * Returns the day of the month (1-31). + * Date.new(2001, 2, 3).mday # => 3 * - * Date.new(2001,2,3).mday #=> 3 */ static VALUE d_lite_mday(VALUE self) @@ -5012,11 +5547,12 @@ d_lite_mday(VALUE self) /* * call-seq: - * d.day_fraction -> rational + * day_fraction -> rational * - * Returns the fractional part of the day. + * Returns the fractional part of the day in range (Rational(0, 1)...Rational(1, 1)): + * + * DateTime.new(2001,2,3,12).day_fraction # => (1/2) * - * DateTime.new(2001,2,3,12).day_fraction #=> (1/2) */ static VALUE d_lite_day_fraction(VALUE self) @@ -5029,12 +5565,14 @@ d_lite_day_fraction(VALUE self) /* * call-seq: - * d.cwyear -> integer + * cwyear -> integer + * + * Returns commercial-date year for +self+ + * (see Date.commercial): * - * Returns the calendar week based year. + * Date.new(2001, 2, 3).cwyear # => 2001 + * Date.new(2000, 1, 1).cwyear # => 1999 * - * Date.new(2001,2,3).cwyear #=> 2001 - * Date.new(2000,1,1).cwyear #=> 1999 */ static VALUE d_lite_cwyear(VALUE self) @@ -5045,11 +5583,13 @@ d_lite_cwyear(VALUE self) /* * call-seq: - * d.cweek -> fixnum + * cweek -> integer * - * Returns the calendar week number (1-53). + * Returns commercial-date week index for +self+ + * (see Date.commercial): + * + * Date.new(2001, 2, 3).cweek # => 5 * - * Date.new(2001,2,3).cweek #=> 5 */ static VALUE d_lite_cweek(VALUE self) @@ -5060,11 +5600,14 @@ d_lite_cweek(VALUE self) /* * call-seq: - * d.cwday -> fixnum + * cwday -> integer + * + * Returns the commercial-date weekday index for +self+ + * (see Date.commercial); + * 1 is Monday: * - * Returns the day of calendar week (1-7, Monday is 1). + * Date.new(2001, 2, 3).cwday # => 6 * - * Date.new(2001,2,3).cwday #=> 6 */ static VALUE d_lite_cwday(VALUE self) @@ -5074,6 +5617,7 @@ d_lite_cwday(VALUE self) } #ifndef NDEBUG +/* :nodoc: */ static VALUE d_lite_wnum0(VALUE self) { @@ -5081,6 +5625,7 @@ d_lite_wnum0(VALUE self) return INT2FIX(m_wnum0(dat)); } +/* :nodoc: */ static VALUE d_lite_wnum1(VALUE self) { @@ -5091,11 +5636,12 @@ d_lite_wnum1(VALUE self) /* * call-seq: - * d.wday -> fixnum + * wday -> integer * - * Returns the day of week (0-6, Sunday is zero). + * Returns the day of week in range (0..6); Sunday is 0: + * + * Date.new(2001, 2, 3).wday # => 6 * - * Date.new(2001,2,3).wday #=> 6 */ static VALUE d_lite_wday(VALUE self) @@ -5106,9 +5652,9 @@ d_lite_wday(VALUE self) /* * call-seq: - * d.sunday? -> bool + * sunday? -> true or false * - * Returns true if the date is Sunday. + * Returns +true+ if +self+ is a Sunday, +false+ otherwise. */ static VALUE d_lite_sunday_p(VALUE self) @@ -5119,9 +5665,9 @@ d_lite_sunday_p(VALUE self) /* * call-seq: - * d.monday? -> bool + * monday? -> true or false * - * Returns true if the date is Monday. + * Returns +true+ if +self+ is a Monday, +false+ otherwise. */ static VALUE d_lite_monday_p(VALUE self) @@ -5132,9 +5678,9 @@ d_lite_monday_p(VALUE self) /* * call-seq: - * d.tuesday? -> bool + * tuesday? -> true or false * - * Returns true if the date is Tuesday. + * Returns +true+ if +self+ is a Tuesday, +false+ otherwise. */ static VALUE d_lite_tuesday_p(VALUE self) @@ -5145,9 +5691,9 @@ d_lite_tuesday_p(VALUE self) /* * call-seq: - * d.wednesday? -> bool + * wednesday? -> true or false * - * Returns true if the date is Wednesday. + * Returns +true+ if +self+ is a Wednesday, +false+ otherwise. */ static VALUE d_lite_wednesday_p(VALUE self) @@ -5158,9 +5704,9 @@ d_lite_wednesday_p(VALUE self) /* * call-seq: - * d.thursday? -> bool + * thursday? -> true or false * - * Returns true if the date is Thursday. + * Returns +true+ if +self+ is a Thursday, +false+ otherwise. */ static VALUE d_lite_thursday_p(VALUE self) @@ -5171,9 +5717,9 @@ d_lite_thursday_p(VALUE self) /* * call-seq: - * d.friday? -> bool + * friday? -> true or false * - * Returns true if the date is Friday. + * Returns +true+ if +self+ is a Friday, +false+ otherwise. */ static VALUE d_lite_friday_p(VALUE self) @@ -5184,9 +5730,9 @@ d_lite_friday_p(VALUE self) /* * call-seq: - * d.saturday? -> bool + * saturday? -> true or false * - * Returns true if the date is Saturday. + * Returns +true+ if +self+ is a Saturday, +false+ otherwise. */ static VALUE d_lite_saturday_p(VALUE self) @@ -5196,6 +5742,7 @@ d_lite_saturday_p(VALUE self) } #ifndef NDEBUG +/* :nodoc: */ static VALUE d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k) { @@ -5217,11 +5764,12 @@ d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k) /* * call-seq: - * d.hour -> fixnum + * hour -> integer * - * Returns the hour (0-23). + * Returns the hour in range (0..23): + * + * DateTime.new(2001, 2, 3, 4, 5, 6).hour # => 4 * - * DateTime.new(2001,2,3,4,5,6).hour #=> 4 */ static VALUE d_lite_hour(VALUE self) @@ -5232,12 +5780,12 @@ d_lite_hour(VALUE self) /* * call-seq: - * d.min -> fixnum - * d.minute -> fixnum + * min -> integer + * + * Returns the minute in range (0..59): * - * Returns the minute (0-59). + * DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5 * - * DateTime.new(2001,2,3,4,5,6).min #=> 5 */ static VALUE d_lite_min(VALUE self) @@ -5248,12 +5796,12 @@ d_lite_min(VALUE self) /* * call-seq: - * d.sec -> fixnum - * d.second -> fixnum + * sec -> integer * - * Returns the second (0-59). + * Returns the second in range (0..59): + * + * DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6 * - * DateTime.new(2001,2,3,4,5,6).sec #=> 6 */ static VALUE d_lite_sec(VALUE self) @@ -5264,12 +5812,13 @@ d_lite_sec(VALUE self) /* * call-seq: - * d.sec_fraction -> rational - * d.second_fraction -> rational + * sec_fraction -> rational + * + * Returns the fractional part of the second in range + * (Rational(0, 1)...Rational(1, 1)): * - * Returns the fractional part of the second. + * DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2) * - * DateTime.new(2001,2,3,4,5,6.5).sec_fraction #=> (1/2) */ static VALUE d_lite_sec_fraction(VALUE self) @@ -5310,12 +5859,14 @@ d_lite_zone(VALUE self) /* * call-seq: - * d.julian? -> bool + * d.julian? -> true or false + * + * Returns +true+ if the date is before the date of calendar reform, + * +false+ otherwise: * - * Returns true if the date is before the day of calendar reform. + * (Date.new(1582, 10, 15) - 1).julian? # => true + * Date.new(1582, 10, 15).julian? # => false * - * Date.new(1582,10,15).julian? #=> false - * (Date.new(1582,10,15) - 1).julian? #=> true */ static VALUE d_lite_julian_p(VALUE self) @@ -5326,12 +5877,14 @@ d_lite_julian_p(VALUE self) /* * call-seq: - * d.gregorian? -> bool + * gregorian? -> true or false * - * Returns true if the date is on or after the day of calendar reform. + * Returns +true+ if the date is on or after + * the date of calendar reform, +false+ otherwise: + * + * Date.new(1582, 10, 15).gregorian? # => true + * (Date.new(1582, 10, 15) - 1).gregorian? # => false * - * Date.new(1582,10,15).gregorian? #=> true - * (Date.new(1582,10,15) - 1).gregorian? #=> false */ static VALUE d_lite_gregorian_p(VALUE self) @@ -5342,12 +5895,13 @@ d_lite_gregorian_p(VALUE self) /* * call-seq: - * d.leap? -> bool + * leap? -> true or false + * + * Returns +true+ if the year is a leap year, +false+ otherwise: * - * Returns true if the year is a leap year. + * Date.new(2000).leap? # => true + * Date.new(2001).leap? # => false * - * Date.new(2000).leap? #=> true - * Date.new(2001).leap? #=> false */ static VALUE d_lite_leap_p(VALUE self) @@ -5366,12 +5920,25 @@ d_lite_leap_p(VALUE self) /* * call-seq: - * d.start -> float + * start -> float + * + * Returns the Julian start date for calendar reform; + * if not an infinity, the returned value is suitable + * for passing to Date#jd: + * + * d = Date.new(2001, 2, 3, Date::ITALY) + * s = d.start # => 2299161.0 + * Date.jd(s).to_s # => "1582-10-15" * - * Returns the Julian day number denoting the day of calendar reform. + * d = Date.new(2001, 2, 3, Date::ENGLAND) + * s = d.start # => 2361222.0 + * Date.jd(s).to_s # => "1752-09-14" + * + * Date.new(2001, 2, 3, Date::GREGORIAN).start # => -Infinity + * Date.new(2001, 2, 3, Date::JULIAN).start # => Infinity + * + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. * - * Date.new(2001,2,3).start #=> 2299161.0 - * Date.new(2001,2,3,Date::GREGORIAN).start #=> -Infinity */ static VALUE d_lite_start(VALUE self) @@ -5436,12 +6003,17 @@ dup_obj_with_new_start(VALUE obj, double sg) /* * call-seq: - * d.new_start([start=Date::ITALY]) -> date + * new_start(start = Date::ITALY) -> new_date + * + * Returns a copy of +self+ with the given +start+ value: + * + * d0 = Date.new(2000, 2, 3) + * d0.julian? # => false + * d1 = d0.new_start(Date::JULIAN) + * d1.julian? # => true * - * Duplicates self and resets its day of calendar reform. + * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start]. * - * d = Date.new(1582,10,15) - * d.new_start(Date::JULIAN) #=> #<Date: 1582-10-05 ...> */ static VALUE d_lite_new_start(int argc, VALUE *argv, VALUE self) @@ -5460,9 +6032,10 @@ d_lite_new_start(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.italy -> date + * italy -> new_date + * + * Equivalent to Date#new_start with argument Date::ITALY. * - * This method is equivalent to new_start(Date::ITALY). */ static VALUE d_lite_italy(VALUE self) @@ -5472,9 +6045,9 @@ d_lite_italy(VALUE self) /* * call-seq: - * d.england -> date + * england -> new_date * - * This method is equivalent to new_start(Date::ENGLAND). + * Equivalent to Date#new_start with argument Date::ENGLAND. */ static VALUE d_lite_england(VALUE self) @@ -5484,9 +6057,9 @@ d_lite_england(VALUE self) /* * call-seq: - * d.julian -> date + * julian -> new_date * - * This method is equivalent to new_start(Date::JULIAN). + * Equivalent to Date#new_start with argument Date::JULIAN. */ static VALUE d_lite_julian(VALUE self) @@ -5496,9 +6069,9 @@ d_lite_julian(VALUE self) /* * call-seq: - * d.gregorian -> date + * gregorian -> new_date * - * This method is equivalent to new_start(Date::GREGORIAN). + * Equivalent to Date#new_start with argument Date::GREGORIAN. */ static VALUE d_lite_gregorian(VALUE self) @@ -5944,9 +6517,11 @@ minus_dd(VALUE self, VALUE other) * call-seq: * d - other -> date or rational * - * Returns the difference between the two dates if the other is a date - * object. If the other is a numeric value, returns a date object - * pointing +other+ days before self. If the other is a fractional number, + * If the other is a date object, returns a Rational + * whose value is the difference between the two dates in days. + * If the other is a numeric value, returns a date object + * pointing +other+ days before self. + * If the other is a fractional number, * assumes its precision is at most nanosecond. * * Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...> @@ -5979,9 +6554,9 @@ d_lite_minus(VALUE self, VALUE other) /* * call-seq: - * d.next_day([n=1]) -> date + * next_day(n = 1) -> new_date * - * This method is equivalent to d + n. + * Equivalent to Date#+ with argument +n+. */ static VALUE d_lite_next_day(int argc, VALUE *argv, VALUE self) @@ -5996,9 +6571,9 @@ d_lite_next_day(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.prev_day([n=1]) -> date + * prev_day(n = 1) -> new_date * - * This method is equivalent to d - n. + * Equivalent to Date#- with argument +n+. */ static VALUE d_lite_prev_day(int argc, VALUE *argv, VALUE self) @@ -6013,10 +6588,14 @@ d_lite_prev_day(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.succ -> date - * d.next -> date + * d.next -> new_date + * + * Returns a new \Date object representing the following day: + * + * d = Date.new(2001, 2, 3) + * d.to_s # => "2001-02-03" + * d.next.to_s # => "2001-02-04" * - * Returns a date object denoting the following day. */ static VALUE d_lite_next(VALUE self) @@ -6026,26 +6605,30 @@ d_lite_next(VALUE self) /* * call-seq: - * d >> n -> date + * d >> n -> new_date + * + * Returns a new \Date object representing the date + * +n+ months later; +n+ should be a numeric: * - * Returns a date object pointing +n+ months after self. - * The argument +n+ should be a numeric value. + * (Date.new(2001, 2, 3) >> 1).to_s # => "2001-03-03" + * (Date.new(2001, 2, 3) >> -2).to_s # => "2000-12-03" * - * Date.new(2001,2,3) >> 1 #=> #<Date: 2001-03-03 ...> - * Date.new(2001,2,3) >> -2 #=> #<Date: 2000-12-03 ...> + * When the same day does not exist for the new month, + * the last day of that month is used instead: * - * When the same day does not exist for the corresponding month, - * the last day of the month is used instead: + * (Date.new(2001, 1, 31) >> 1).to_s # => "2001-02-28" + * (Date.new(2001, 1, 31) >> -4).to_s # => "2000-09-30" * - * Date.new(2001,1,28) >> 1 #=> #<Date: 2001-02-28 ...> - * Date.new(2001,1,31) >> 1 #=> #<Date: 2001-02-28 ...> + * This results in the following, possibly unexpected, behaviors: * - * This also results in the following, possibly unexpected, behavior: + * d0 = Date.new(2001, 1, 31) + * d1 = d0 >> 1 # => #<Date: 2001-02-28> + * d2 = d1 >> 1 # => #<Date: 2001-03-28> * - * Date.new(2001,1,31) >> 2 #=> #<Date: 2001-03-31 ...> - * Date.new(2001,1,31) >> 1 >> 1 #=> #<Date: 2001-03-28 ...> + * d0 = Date.new(2001, 1, 31) + * d1 = d0 >> 1 # => #<Date: 2001-02-28> + * d2 = d1 >> -1 # => #<Date: 2001-01-28> * - * Date.new(2001,1,31) >> 1 >> -1 #=> #<Date: 2001-01-28 ...> */ static VALUE d_lite_rshift(VALUE self, VALUE other) @@ -6090,24 +6673,28 @@ d_lite_rshift(VALUE self, VALUE other) * call-seq: * d << n -> date * - * Returns a date object pointing +n+ months before self. - * The argument +n+ should be a numeric value. + * Returns a new \Date object representing the date + * +n+ months earlier; +n+ should be a numeric: * - * Date.new(2001,2,3) << 1 #=> #<Date: 2001-01-03 ...> - * Date.new(2001,2,3) << -2 #=> #<Date: 2001-04-03 ...> + * (Date.new(2001, 2, 3) << 1).to_s # => "2001-01-03" + * (Date.new(2001, 2, 3) << -2).to_s # => "2001-04-03" * - * When the same day does not exist for the corresponding month, - * the last day of the month is used instead: + * When the same day does not exist for the new month, + * the last day of that month is used instead: * - * Date.new(2001,3,28) << 1 #=> #<Date: 2001-02-28 ...> - * Date.new(2001,3,31) << 1 #=> #<Date: 2001-02-28 ...> + * (Date.new(2001, 3, 31) << 1).to_s # => "2001-02-28" + * (Date.new(2001, 3, 31) << -6).to_s # => "2001-09-30" * - * This also results in the following, possibly unexpected, behavior: + * This results in the following, possibly unexpected, behaviors: * - * Date.new(2001,3,31) << 2 #=> #<Date: 2001-01-31 ...> - * Date.new(2001,3,31) << 1 << 1 #=> #<Date: 2001-01-28 ...> + * d0 = Date.new(2001, 3, 31) + * d0 << 2 # => #<Date: 2001-01-31> + * d0 << 1 << 1 # => #<Date: 2001-01-28> + * + * d0 = Date.new(2001, 3, 31) + * d1 = d0 << 1 # => #<Date: 2001-02-28> + * d2 = d1 << -1 # => #<Date: 2001-03-28> * - * Date.new(2001,3,31) << 1 << -1 #=> #<Date: 2001-03-28 ...> */ static VALUE d_lite_lshift(VALUE self, VALUE other) @@ -6118,11 +6705,9 @@ d_lite_lshift(VALUE self, VALUE other) /* * call-seq: - * d.next_month([n=1]) -> date - * - * This method is equivalent to d >> n. + * next_month(n = 1) -> new_date * - * See Date#>> for examples. + * Equivalent to #>> with argument +n+. */ static VALUE d_lite_next_month(int argc, VALUE *argv, VALUE self) @@ -6137,11 +6722,9 @@ d_lite_next_month(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.prev_month([n=1]) -> date - * - * This method is equivalent to d << n. + * prev_month(n = 1) -> new_date * - * See Date#<< for examples. + * Equivalent to #<< with argument +n+. */ static VALUE d_lite_prev_month(int argc, VALUE *argv, VALUE self) @@ -6156,15 +6739,9 @@ d_lite_prev_month(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.next_year([n=1]) -> date + * next_year(n = 1) -> new_date * - * This method is equivalent to d >> (n * 12). - * - * Date.new(2001,2,3).next_year #=> #<Date: 2002-02-03 ...> - * Date.new(2008,2,29).next_year #=> #<Date: 2009-02-28 ...> - * Date.new(2008,2,29).next_year(4) #=> #<Date: 2012-02-29 ...> - * - * See also Date#>>. + * Equivalent to #>> with argument <tt>n * 12</tt>. */ static VALUE d_lite_next_year(int argc, VALUE *argv, VALUE self) @@ -6179,15 +6756,9 @@ d_lite_next_year(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.prev_year([n=1]) -> date - * - * This method is equivalent to d << (n * 12). - * - * Date.new(2001,2,3).prev_year #=> #<Date: 2000-02-03 ...> - * Date.new(2008,2,29).prev_year #=> #<Date: 2007-02-28 ...> - * Date.new(2008,2,29).prev_year(4) #=> #<Date: 2004-02-29 ...> + * prev_year(n = 1) -> new_date * - * See also Date#<<. + * Equivalent to #<< with argument <tt>n * 12</tt>. */ static VALUE d_lite_prev_year(int argc, VALUE *argv, VALUE self) @@ -6204,14 +6775,33 @@ static VALUE d_lite_cmp(VALUE, VALUE); /* * call-seq: - * d.step(limit[, step=1]) -> enumerator - * d.step(limit[, step=1]){|date| ...} -> self + * step(limit, step = 1){|date| ... } -> self + * + * Calls the block with specified dates; + * returns +self+. + * + * - The first +date+ is +self+. + * - Each successive +date+ is <tt>date + step</tt>, + * where +step+ is the numeric step size in days. + * - The last date is the last one that is before or equal to +limit+, + * which should be a \Date object. + * + * Example: + * + * limit = Date.new(2001, 12, 31) + * Date.new(2001).step(limit){|date| p date.to_s if date.mday == 31 } * - * Iterates evaluation of the given block, which takes a date object. - * The limit should be a date object. + * Output: * - * Date.new(2001).step(Date.new(2001,-1,-1)).select{|d| d.sunday?}.size - * #=> 52 + * "2001-01-31" + * "2001-03-31" + * "2001-05-31" + * "2001-07-31" + * "2001-08-31" + * "2001-10-31" + * "2001-12-31" + * + * Returns an Enumerator if no block is given. */ static VALUE d_lite_step(int argc, VALUE *argv, VALUE self) @@ -6254,10 +6844,9 @@ d_lite_step(int argc, VALUE *argv, VALUE self) /* * call-seq: - * d.upto(max) -> enumerator - * d.upto(max){|date| ...} -> self + * upto(max){|date| ... } -> self * - * This method is equivalent to step(max, 1){|date| ...}. + * Equivalent to #step with arguments +max+ and +1+. */ static VALUE d_lite_upto(VALUE self, VALUE max) @@ -6276,10 +6865,9 @@ d_lite_upto(VALUE self, VALUE max) /* * call-seq: - * d.downto(min) -> enumerator - * d.downto(min){|date| ...} -> self + * downto(min){|date| ... } -> self * - * This method is equivalent to step(min, -1){|date| ...}. + * Equivalent to #step with arguments +min+ and <tt>-1</tt>. */ static VALUE d_lite_downto(VALUE self, VALUE min) @@ -6367,19 +6955,43 @@ cmp_dd(VALUE self, VALUE other) /* * call-seq: - * d <=> other -> -1, 0, +1 or nil + * self <=> other -> -1, 0, 1 or nil + * + * Compares +self+ and +other+, returning: + * + * - <tt>-1</tt> if +other+ is larger. + * - <tt>0</tt> if the two are equal. + * - <tt>1</tt> if +other+ is smaller. + * - +nil+ if the two are incomparable. + * + * Argument +other+ may be: + * + * - Another \Date object: + * + * d = Date.new(2022, 7, 27) # => #<Date: 2022-07-27 ((2459788j,0s,0n),+0s,2299161j)> + * prev_date = d.prev_day # => #<Date: 2022-07-26 ((2459787j,0s,0n),+0s,2299161j)> + * next_date = d.next_day # => #<Date: 2022-07-28 ((2459789j,0s,0n),+0s,2299161j)> + * d <=> next_date # => -1 + * d <=> d # => 0 + * d <=> prev_date # => 1 + * + * - A DateTime object: * - * Compares the two dates and returns -1, zero, 1 or nil. The other - * should be a date object or a numeric value as an astronomical - * Julian day number. + * d <=> DateTime.new(2022, 7, 26) # => 1 + * d <=> DateTime.new(2022, 7, 27) # => 0 + * d <=> DateTime.new(2022, 7, 28) # => -1 * - * Date.new(2001,2,3) <=> Date.new(2001,2,4) #=> -1 - * Date.new(2001,2,3) <=> Date.new(2001,2,3) #=> 0 - * Date.new(2001,2,3) <=> Date.new(2001,2,2) #=> 1 - * Date.new(2001,2,3) <=> Object.new #=> nil - * Date.new(2001,2,3) <=> Rational(4903887,2) #=> 0 + * - A numeric (compares <tt>self.ajd</tt> to +other+): + * + * d <=> 2459788 # => -1 + * d <=> 2459787 # => 1 + * d <=> 2459786 # => 1 + * d <=> d.ajd # => 0 + * + * - Any other object: + * + * d <=> Object.new # => nil * - * See also Comparable. */ static VALUE d_lite_cmp(VALUE self, VALUE other) @@ -6439,20 +7051,39 @@ equal_gen(VALUE self, VALUE other) /* * call-seq: - * d === other -> bool - * - * Returns true if they are the same day. - * - * Date.new(2001,2,3) === Date.new(2001,2,3) - * #=> true - * Date.new(2001,2,3) === Date.new(2001,2,4) - * #=> false - * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,12) - * #=> true - * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,0,0,0,'+24:00') - * #=> true - * DateTime.new(2001,2,3) === DateTime.new(2001,2,4,0,0,0,'+24:00') - * #=> false + * self === other -> true, false, or nil. + * + * Returns +true+ if +self+ and +other+ represent the same date, + * +false+ if not, +nil+ if the two are not comparable. + * + * Argument +other+ may be: + * + * - Another \Date object: + * + * d = Date.new(2022, 7, 27) # => #<Date: 2022-07-27 ((2459788j,0s,0n),+0s,2299161j)> + * prev_date = d.prev_day # => #<Date: 2022-07-26 ((2459787j,0s,0n),+0s,2299161j)> + * next_date = d.next_day # => #<Date: 2022-07-28 ((2459789j,0s,0n),+0s,2299161j)> + * d === prev_date # => false + * d === d # => true + * d === next_date # => false + * + * - A DateTime object: + * + * d === DateTime.new(2022, 7, 26) # => false + * d === DateTime.new(2022, 7, 27) # => true + * d === DateTime.new(2022, 7, 28) # => false + * + * - A numeric (compares <tt>self.jd</tt> to +other+): + * + * d === 2459788 # => true + * d === 2459787 # => false + * d === 2459786 # => false + * d === d.jd # => true + * + * - An object not comparable: + * + * d === Object.new # => nil + * */ static VALUE d_lite_equal(VALUE self, VALUE other) @@ -6497,13 +7128,24 @@ d_lite_eql_p(VALUE self, VALUE other) static VALUE d_lite_hash(VALUE self) { - st_index_t v, h[4]; + st_index_t v, h[5]; + VALUE nth; get_d1(self); - h[0] = m_nth(dat); - h[1] = m_jd(dat); - h[2] = m_df(dat); - h[3] = m_sf(dat); + nth = m_nth(dat); + + if (FIXNUM_P(nth)) { + h[0] = 0; + h[1] = (st_index_t)nth; + } else { + h[0] = 1; + h[1] = (st_index_t)FIX2LONG(rb_hash(nth)); + } + + h[2] = m_jd(dat); + h[3] = m_df(dat); + h[4] = m_sf(dat); + v = rb_memhash(h, sizeof(h)); return ST2FIX(v); } @@ -6515,12 +7157,14 @@ static VALUE strftimev(const char *, VALUE, /* * call-seq: - * d.to_s -> string + * to_s -> string * - * Returns a string in an ISO 8601 format. (This method doesn't use the - * expanded representations.) + * Returns a string representation of the date in +self+ + * in {ISO 8601 extended date format}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications] + * (<tt>'%Y-%m-%d'</tt>): + * + * Date.new(2001, 2, 3).to_s # => "2001-02-03" * - * Date.new(2001,2,3).to_s #=> "2001-02-03" */ static VALUE d_lite_to_s(VALUE self) @@ -6529,6 +7173,7 @@ d_lite_to_s(VALUE self) } #ifndef NDEBUG +/* :nodoc: */ static VALUE mk_inspect_raw(union DateData *x, VALUE klass) { @@ -6578,6 +7223,7 @@ mk_inspect_raw(union DateData *x, VALUE klass) } } +/* :nodoc: */ static VALUE d_lite_inspect_raw(VALUE self) { @@ -6599,14 +7245,13 @@ mk_inspect(union DateData *x, VALUE klass, VALUE to_s) /* * call-seq: - * d.inspect -> string + * inspect -> string * - * Returns the value as a string for inspection. + * Returns a string representation of +self+: + * + * Date.new(2001, 2, 3).inspect + * # => "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>" * - * Date.new(2001,2,3).inspect - * #=> "#<Date: 2001-02-03>" - * DateTime.new(2001,2,3,4,5,6,'-7').inspect - * #=> "#<DateTime: 2001-02-03T04:05:06-07:00>" */ static VALUE d_lite_inspect(VALUE self) @@ -6788,180 +7433,16 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self, /* * call-seq: - * d.strftime([format='%F']) -> string - * - * Formats date according to the directives in the given format - * string. - * The directives begin with a percent (%) character. - * Any text not listed as a directive will be passed through to the - * output string. - * - * A directive consists of a percent (%) character, - * zero or more flags, an optional minimum field width, - * an optional modifier, and a conversion specifier - * as follows. - * - * %<flags><width><modifier><conversion> - * - * Flags: - * - don't pad a numerical output. - * _ use spaces for padding. - * 0 use zeros for padding. - * ^ upcase the result string. - * # change case. - * - * The minimum field width specifies the minimum width. - * - * The modifiers are "E", "O", ":", "::" and ":::". - * "E" and "O" are ignored. No effect to result currently. - * - * Format directives: - * - * Date (Year, Month, Day): - * %Y - Year with century (can be negative, 4 digits at least) - * -0001, 0000, 1995, 2009, 14292, etc. - * %C - year / 100 (round down. 20 in 2009) - * %y - year % 100 (00..99) - * - * %m - Month of the year, zero-padded (01..12) - * %_m blank-padded ( 1..12) - * %-m no-padded (1..12) - * %B - The full month name (``January'') - * %^B uppercased (``JANUARY'') - * %b - The abbreviated month name (``Jan'') - * %^b uppercased (``JAN'') - * %h - Equivalent to %b - * - * %d - Day of the month, zero-padded (01..31) - * %-d no-padded (1..31) - * %e - Day of the month, blank-padded ( 1..31) - * - * %j - Day of the year (001..366) - * - * Time (Hour, Minute, Second, Subsecond): - * %H - Hour of the day, 24-hour clock, zero-padded (00..23) - * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23) - * %I - Hour of the day, 12-hour clock, zero-padded (01..12) - * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12) - * %P - Meridian indicator, lowercase (``am'' or ``pm'') - * %p - Meridian indicator, uppercase (``AM'' or ``PM'') - * - * %M - Minute of the hour (00..59) - * - * %S - Second of the minute (00..60) - * - * %L - Millisecond of the second (000..999) - * %N - Fractional seconds digits, default is 9 digits (nanosecond) - * %3N millisecond (3 digits) %15N femtosecond (15 digits) - * %6N microsecond (6 digits) %18N attosecond (18 digits) - * %9N nanosecond (9 digits) %21N zeptosecond (21 digits) - * %12N picosecond (12 digits) %24N yoctosecond (24 digits) - * - * Time zone: - * %z - Time zone as hour and minute offset from UTC (e.g. +0900) - * %:z - hour and minute offset from UTC with a colon (e.g. +09:00) - * %::z - hour, minute and second offset from UTC (e.g. +09:00:00) - * %:::z - hour, minute and second offset from UTC - * (e.g. +09, +09:30, +09:30:30) - * %Z - Equivalent to %:z (e.g. +09:00) - * - * Weekday: - * %A - The full weekday name (``Sunday'') - * %^A uppercased (``SUNDAY'') - * %a - The abbreviated name (``Sun'') - * %^a uppercased (``SUN'') - * %u - Day of the week (Monday is 1, 1..7) - * %w - Day of the week (Sunday is 0, 0..6) - * - * ISO 8601 week-based year and week number: - * The week 1 of YYYY starts with a Monday and includes YYYY-01-04. - * The days in the year before the first week are in the last week of - * the previous year. - * %G - The week-based year - * %g - The last 2 digits of the week-based year (00..99) - * %V - Week number of the week-based year (01..53) - * - * Week number: - * The week 1 of YYYY starts with a Sunday or Monday (according to %U - * or %W). The days in the year before the first week are in week 0. - * %U - Week number of the year. The week starts with Sunday. (00..53) - * %W - Week number of the year. The week starts with Monday. (00..53) - * - * Seconds since the Unix Epoch: - * %s - Number of seconds since 1970-01-01 00:00:00 UTC. - * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC. - * - * Literal string: - * %n - Newline character (\n) - * %t - Tab character (\t) - * %% - Literal ``%'' character - * - * Combination: - * %c - date and time (%a %b %e %T %Y) - * %D - Date (%m/%d/%y) - * %F - The ISO 8601 date format (%Y-%m-%d) - * %v - VMS date (%e-%b-%Y) - * %x - Same as %D - * %X - Same as %T - * %r - 12-hour time (%I:%M:%S %p) - * %R - 24-hour time (%H:%M) - * %T - 24-hour time (%H:%M:%S) - * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y) - * - * This method is similar to the strftime() function defined in ISO C - * and POSIX. - * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z) - * are locale dependent in the function. - * However, this method is locale independent. - * So, the result may differ even if the same format string is used in other - * systems such as C. - * It is good practice to avoid %x and %X because there are corresponding - * locale independent representations, %D and %T. - * - * Examples: - * - * d = DateTime.new(2007,11,19,8,37,48,"-06:00") - * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...> - * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007" - * d.strftime("at %I:%M%p") #=> "at 08:37AM" - * - * Various ISO 8601 formats: - * %Y%m%d => 20071119 Calendar date (basic) - * %F => 2007-11-19 Calendar date (extended) - * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month - * %Y => 2007 Calendar date, reduced accuracy, specific year - * %C => 20 Calendar date, reduced accuracy, specific century - * %Y%j => 2007323 Ordinal date (basic) - * %Y-%j => 2007-323 Ordinal date (extended) - * %GW%V%u => 2007W471 Week date (basic) - * %G-W%V-%u => 2007-W47-1 Week date (extended) - * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic) - * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended) - * %H%M%S => 083748 Local time (basic) - * %T => 08:37:48 Local time (extended) - * %H%M => 0837 Local time, reduced accuracy, specific minute (basic) - * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended) - * %H => 08 Local time, reduced accuracy, specific hour - * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic) - * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended) - * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic) - * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended) - * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic) - * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended) - * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic) - * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended) - * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic) - * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended) - * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic) - * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended) - * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic) - * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended) - * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic) - * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended) - * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic) - * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended) - * - * See also strftime(3) and ::strptime. + * strftime(format = '%F') -> string + * + * Returns a string representation of the date in +self+, + * formatted according the given +format+: + * + * Date.new(2001, 2, 3).strftime # => "2001-02-03" + * + * For other formats, see + * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]. + * */ static VALUE d_lite_strftime(int argc, VALUE *argv, VALUE self) @@ -6989,13 +7470,16 @@ strftimev(const char *fmt, VALUE self, /* * call-seq: - * d.asctime -> string - * d.ctime -> string + * asctime -> string * - * Returns a string in asctime(3) format (but without "\n\0" at the - * end). This method is equivalent to strftime('%c'). + * Equivalent to #strftime with argument <tt>'%a %b %e %T %Y'</tt> + * (or its {shorthand form}[rdoc-ref:language/strftime_formatting.rdoc@Shorthand+Conversion+Specifiers] + * <tt>'%c'</tt>): + * + * Date.new(2001, 2, 3).asctime # => "Sat Feb 3 00:00:00 2001" + * + * See {asctime}[https://man7.org/linux/man-pages/man3/asctime.3p.html]. * - * See also asctime(3) or ctime(3). */ static VALUE d_lite_asctime(VALUE self) @@ -7005,10 +7489,14 @@ d_lite_asctime(VALUE self) /* * call-seq: - * d.iso8601 -> string - * d.xmlschema -> string + * iso8601 -> string + * + * Equivalent to #strftime with argument <tt>'%Y-%m-%d'</tt> + * (or its {shorthand form}[rdoc-ref:language/strftime_formatting.rdoc@Shorthand+Conversion+Specifiers] + * <tt>'%F'</tt>); + * + * Date.new(2001, 2, 3).iso8601 # => "2001-02-03" * - * This method is equivalent to strftime('%F'). */ static VALUE d_lite_iso8601(VALUE self) @@ -7018,9 +7506,13 @@ d_lite_iso8601(VALUE self) /* * call-seq: - * d.rfc3339 -> string + * rfc3339 -> string + * + * Equivalent to #strftime with argument <tt>'%FT%T%:z'</tt>; + * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]: + * + * Date.new(2001, 2, 3).rfc3339 # => "2001-02-03T00:00:00+00:00" * - * This method is equivalent to strftime('%FT%T%:z'). */ static VALUE d_lite_rfc3339(VALUE self) @@ -7030,10 +7522,13 @@ d_lite_rfc3339(VALUE self) /* * call-seq: - * d.rfc2822 -> string - * d.rfc822 -> string + * rfc2822 -> string + * + * Equivalent to #strftime with argument <tt>'%a, %-d %b %Y %T %z'</tt>; + * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]: + * + * Date.new(2001, 2, 3).rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000" * - * This method is equivalent to strftime('%a, %-d %b %Y %T %z'). */ static VALUE d_lite_rfc2822(VALUE self) @@ -7043,10 +7538,13 @@ d_lite_rfc2822(VALUE self) /* * call-seq: - * d.httpdate -> string + * httpdate -> string + * + * Equivalent to #strftime with argument <tt>'%a, %d %b %Y %T GMT'</tt>; + * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]: + * + * Date.new(2001, 2, 3).httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT" * - * This method is equivalent to strftime('%a, %d %b %Y %T GMT'). - * See also RFC 2616. */ static VALUE d_lite_httpdate(VALUE self) @@ -7097,11 +7595,13 @@ jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y) /* * call-seq: - * d.jisx0301 -> string + * jisx0301 -> string * - * Returns a string in a JIS X 0301 format. + * Returns a string representation of the date in +self+ + * in JIS X 0301 format. + * + * Date.new(2001, 2, 3).jisx0301 # => "H13.02.03" * - * Date.new(2001,2,3).jisx0301 #=> "H13.02.03" */ static VALUE d_lite_jisx0301(VALUE self) @@ -7116,7 +7616,98 @@ d_lite_jisx0301(VALUE self) return strftimev(fmt, self, set_tmx); } +static VALUE +deconstruct_keys(VALUE self, VALUE keys, int is_datetime) +{ + VALUE h = rb_hash_new(); + long i; + + get_d1(self); + + if (NIL_P(keys)) { + rb_hash_aset(h, sym_year, m_real_year(dat)); + rb_hash_aset(h, sym_month, INT2FIX(m_mon(dat))); + rb_hash_aset(h, sym_day, INT2FIX(m_mday(dat))); + rb_hash_aset(h, sym_yday, INT2FIX(m_yday(dat))); + rb_hash_aset(h, sym_wday, INT2FIX(m_wday(dat))); + if (is_datetime) { + rb_hash_aset(h, sym_hour, INT2FIX(m_hour(dat))); + rb_hash_aset(h, sym_min, INT2FIX(m_min(dat))); + rb_hash_aset(h, sym_sec, INT2FIX(m_sec(dat))); + rb_hash_aset(h, sym_sec_fraction, m_sf_in_sec(dat)); + rb_hash_aset(h, sym_zone, m_zone(dat)); + } + + return h; + } + if (!RB_TYPE_P(keys, T_ARRAY)) { + rb_raise(rb_eTypeError, + "wrong argument type %"PRIsVALUE" (expected Array or nil)", + rb_obj_class(keys)); + + } + + for (i=0; i<RARRAY_LEN(keys); i++) { + VALUE key = RARRAY_AREF(keys, i); + + if (sym_year == key) rb_hash_aset(h, key, m_real_year(dat)); + if (sym_month == key) rb_hash_aset(h, key, INT2FIX(m_mon(dat))); + if (sym_day == key) rb_hash_aset(h, key, INT2FIX(m_mday(dat))); + if (sym_yday == key) rb_hash_aset(h, key, INT2FIX(m_yday(dat))); + if (sym_wday == key) rb_hash_aset(h, key, INT2FIX(m_wday(dat))); + if (is_datetime) { + if (sym_hour == key) rb_hash_aset(h, key, INT2FIX(m_hour(dat))); + if (sym_min == key) rb_hash_aset(h, key, INT2FIX(m_min(dat))); + if (sym_sec == key) rb_hash_aset(h, key, INT2FIX(m_sec(dat))); + if (sym_sec_fraction == key) rb_hash_aset(h, key, m_sf_in_sec(dat)); + if (sym_zone == key) rb_hash_aset(h, key, m_zone(dat)); + } + } + return h; +} + +/* + * call-seq: + * deconstruct_keys(array_of_names_or_nil) -> hash + * + * Returns a hash of the name/value pairs, to use in pattern matching. + * Possible keys are: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, + * <tt>:wday</tt>, <tt>:yday</tt>. + * + * Possible usages: + * + * d = Date.new(2022, 10, 5) + * + * if d in wday: 3, day: ..7 # uses deconstruct_keys underneath + * puts "first Wednesday of the month" + * end + * #=> prints "first Wednesday of the month" + * + * case d + * in year: ...2022 + * puts "too old" + * in month: ..9 + * puts "quarter 1-3" + * in wday: 1..5, month: + * puts "working day in month #{month}" + * end + * #=> prints "working day in month 10" + * + * Note that deconstruction by pattern can also be combined with class check: + * + * if d in Date(wday: 3, day: ..7) + * puts "first Wednesday of the month" + * end + * + */ +static VALUE +d_lite_deconstruct_keys(VALUE self, VALUE keys) +{ + return deconstruct_keys(self, keys, /* is_datetime=false */ 0); +} + #ifndef NDEBUG +/* :nodoc: */ static VALUE d_lite_marshal_dump_old(VALUE self) { @@ -7129,10 +7720,7 @@ d_lite_marshal_dump_old(VALUE self) m_of_in_day(dat), DBL2NUM(m_sg(dat))); - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } + rb_copy_generic_ivar(a, self); return a; } @@ -7154,10 +7742,8 @@ d_lite_marshal_dump(VALUE self) INT2FIX(m_of(dat)), DBL2NUM(m_sg(dat))); - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } + + rb_copy_generic_ivar(a, self); return a; } @@ -7230,10 +7816,7 @@ d_lite_marshal_load(VALUE self, VALUE a) HAVE_JD | HAVE_DF); } - if (FL_TEST(a, FL_EXIVAR)) { - rb_copy_generic_ivar(self, a); - FL_SET(self, FL_EXIVAR); - } + rb_copy_generic_ivar(self, a); return self; } @@ -7404,17 +7987,7 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass) } /* - * call-seq: - * DateTime.civil([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime - * DateTime.new([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime - * - * Creates a DateTime object denoting the given calendar date. - * - * DateTime.new(2001,2,3) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> - * DateTime.new(2001,2,3,4,5,6,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> - * DateTime.new(2001,-11,-26,-20,-55,-54,'+7') - * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> + * Same as DateTime.new. */ static VALUE datetime_s_civil(int argc, VALUE *argv, VALUE klass) @@ -7604,6 +8177,7 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass) } #ifndef NDEBUG +/* :nodoc: */ static VALUE datetime_s_weeknum(int argc, VALUE *argv, VALUE klass) { @@ -7673,6 +8247,7 @@ datetime_s_weeknum(int argc, VALUE *argv, VALUE klass) return ret; } +/* :nodoc: */ static VALUE datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass) { @@ -7797,7 +8372,7 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass) #ifdef HAVE_STRUCT_TM_TM_GMTOFF of = tm.tm_gmtoff; #elif defined(HAVE_TIMEZONE) -#ifdef HAVE_ALTZONE +#if defined(HAVE_ALTZONE) && !defined(_AIX) of = (long)-((tm.tm_isdst > 0) ? altzone : timezone); #else of = (long)-timezone; @@ -7994,7 +8569,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: fmt = rb_str_new2("%FT%T%z"); case 2: @@ -8013,14 +8588,14 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime + * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime * * Parses the given representation of date and time, and creates a * DateTime object. * - * This method **does not** function as a validator. If the input + * This method *does* *not* function as a validator. If the input * string does not match valid formats strictly, you may get a cryptic - * result. Should consider to use `DateTime.strptime` instead of this + * result. Should consider to use DateTime.strptime instead of this * method as possible. * * If the optional second argument is true and the detected year is in @@ -8032,17 +8607,21 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> * DateTime.parse('3rd Feb 2001 04:05:06 PM') * #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_parse(int argc, VALUE *argv, VALUE klass) { - VALUE str, comp, sg; + VALUE str, comp, sg, opt; - rb_scan_args(argc, argv, "03", &str, &comp, &sg); + argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: comp = Qtrue; case 2: @@ -8050,18 +8629,20 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) } { - VALUE argv2[2], hash; - - argv2[0] = str; - argv2[1] = comp; - hash = date_s__parse(2, argv2, klass); + int argc2 = 2; + VALUE argv2[3], hash; + argv2[0] = str; + argv2[1] = comp; + argv2[2] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__parse(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical ISO 8601 formats. @@ -8072,114 +8653,150 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> * DateTime.iso8601('2001-W05-6T04:05:06+07:00') * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__iso8601(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__iso8601(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical RFC 3339 formats. * * DateTime.rfc3339('2001-02-03T04:05:06+07:00') * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__rfc3339(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__rfc3339(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical XML Schema formats. * * DateTime.xmlschema('2001-02-03T04:05:06+07:00') * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__xmlschema(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__xmlschema(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime - * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime + * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime + * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical RFC 2822 formats. * * DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700') * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__rfc2822(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__rfc2822(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } @@ -8193,30 +8810,39 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) * * DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT') * #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__httpdate(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__httpdate(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } /* * call-seq: - * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime + * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime * * Creates a new DateTime object by parsing from a string according to * some typical JIS X 0301 formats. @@ -8228,23 +8854,32 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) * * DateTime.jisx0301('13.02.03T04:05:06+07:00') * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> + * + * Raise an ArgumentError when the string length is longer than _limit_. + * You can stop this check by passing <code>limit: nil</code>, but note + * that it may take a long time to parse. */ static VALUE datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) { - VALUE str, sg; + VALUE str, sg, opt; - rb_scan_args(argc, argv, "02", &str, &sg); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } { - VALUE hash = date_s__jisx0301(klass, str); + int argc2 = 1; + VALUE argv2[2], hash; + argv2[0] = str; + argv2[1] = opt; + if (!NIL_P(opt)) argc2++; + hash = date_s__jisx0301(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } } @@ -8267,181 +8902,16 @@ dt_lite_to_s(VALUE self) /* * call-seq: - * dt.strftime([format='%FT%T%:z']) -> string - * - * Formats date according to the directives in the given format - * string. - * The directives begin with a percent (%) character. - * Any text not listed as a directive will be passed through to the - * output string. - * - * A directive consists of a percent (%) character, - * zero or more flags, an optional minimum field width, - * an optional modifier, and a conversion specifier - * as follows. - * - * %<flags><width><modifier><conversion> - * - * Flags: - * - don't pad a numerical output. - * _ use spaces for padding. - * 0 use zeros for padding. - * ^ upcase the result string. - * # change case. - * : use colons for %z. - * - * The minimum field width specifies the minimum width. - * - * The modifiers are "E" and "O". - * They are ignored. - * - * Format directives: - * - * Date (Year, Month, Day): - * %Y - Year with century (can be negative, 4 digits at least) - * -0001, 0000, 1995, 2009, 14292, etc. - * %C - year / 100 (round down. 20 in 2009) - * %y - year % 100 (00..99) - * - * %m - Month of the year, zero-padded (01..12) - * %_m blank-padded ( 1..12) - * %-m no-padded (1..12) - * %B - The full month name (``January'') - * %^B uppercased (``JANUARY'') - * %b - The abbreviated month name (``Jan'') - * %^b uppercased (``JAN'') - * %h - Equivalent to %b - * - * %d - Day of the month, zero-padded (01..31) - * %-d no-padded (1..31) - * %e - Day of the month, blank-padded ( 1..31) - * - * %j - Day of the year (001..366) - * - * Time (Hour, Minute, Second, Subsecond): - * %H - Hour of the day, 24-hour clock, zero-padded (00..23) - * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23) - * %I - Hour of the day, 12-hour clock, zero-padded (01..12) - * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12) - * %P - Meridian indicator, lowercase (``am'' or ``pm'') - * %p - Meridian indicator, uppercase (``AM'' or ``PM'') - * - * %M - Minute of the hour (00..59) - * - * %S - Second of the minute (00..60) - * - * %L - Millisecond of the second (000..999) - * %N - Fractional seconds digits, default is 9 digits (nanosecond) - * %3N millisecond (3 digits) %15N femtosecond (15 digits) - * %6N microsecond (6 digits) %18N attosecond (18 digits) - * %9N nanosecond (9 digits) %21N zeptosecond (21 digits) - * %12N picosecond (12 digits) %24N yoctosecond (24 digits) - * - * Time zone: - * %z - Time zone as hour and minute offset from UTC (e.g. +0900) - * %:z - hour and minute offset from UTC with a colon (e.g. +09:00) - * %::z - hour, minute and second offset from UTC (e.g. +09:00:00) - * %:::z - hour, minute and second offset from UTC - * (e.g. +09, +09:30, +09:30:30) - * %Z - Equivalent to %:z (e.g. +09:00) - * - * Weekday: - * %A - The full weekday name (``Sunday'') - * %^A uppercased (``SUNDAY'') - * %a - The abbreviated name (``Sun'') - * %^a uppercased (``SUN'') - * %u - Day of the week (Monday is 1, 1..7) - * %w - Day of the week (Sunday is 0, 0..6) - * - * ISO 8601 week-based year and week number: - * The week 1 of YYYY starts with a Monday and includes YYYY-01-04. - * The days in the year before the first week are in the last week of - * the previous year. - * %G - The week-based year - * %g - The last 2 digits of the week-based year (00..99) - * %V - Week number of the week-based year (01..53) - * - * Week number: - * The week 1 of YYYY starts with a Sunday or Monday (according to %U - * or %W). The days in the year before the first week are in week 0. - * %U - Week number of the year. The week starts with Sunday. (00..53) - * %W - Week number of the year. The week starts with Monday. (00..53) - * - * Seconds since the Unix Epoch: - * %s - Number of seconds since 1970-01-01 00:00:00 UTC. - * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC. - * - * Literal string: - * %n - Newline character (\n) - * %t - Tab character (\t) - * %% - Literal ``%'' character - * - * Combination: - * %c - date and time (%a %b %e %T %Y) - * %D - Date (%m/%d/%y) - * %F - The ISO 8601 date format (%Y-%m-%d) - * %v - VMS date (%e-%b-%Y) - * %x - Same as %D - * %X - Same as %T - * %r - 12-hour time (%I:%M:%S %p) - * %R - 24-hour time (%H:%M) - * %T - 24-hour time (%H:%M:%S) - * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y) - * - * This method is similar to the strftime() function defined in ISO C - * and POSIX. - * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z) - * are locale dependent in the function. - * However, this method is locale independent. - * So, the result may differ even if the same format string is used in other - * systems such as C. - * It is good practice to avoid %x and %X because there are corresponding - * locale independent representations, %D and %T. - * - * Examples: - * - * d = DateTime.new(2007,11,19,8,37,48,"-06:00") - * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...> - * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007" - * d.strftime("at %I:%M%p") #=> "at 08:37AM" - * - * Various ISO 8601 formats: - * %Y%m%d => 20071119 Calendar date (basic) - * %F => 2007-11-19 Calendar date (extended) - * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month - * %Y => 2007 Calendar date, reduced accuracy, specific year - * %C => 20 Calendar date, reduced accuracy, specific century - * %Y%j => 2007323 Ordinal date (basic) - * %Y-%j => 2007-323 Ordinal date (extended) - * %GW%V%u => 2007W471 Week date (basic) - * %G-W%V-%u => 2007-W47-1 Week date (extended) - * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic) - * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended) - * %H%M%S => 083748 Local time (basic) - * %T => 08:37:48 Local time (extended) - * %H%M => 0837 Local time, reduced accuracy, specific minute (basic) - * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended) - * %H => 08 Local time, reduced accuracy, specific hour - * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic) - * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended) - * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic) - * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended) - * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic) - * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended) - * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic) - * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended) - * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic) - * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended) - * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic) - * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended) - * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic) - * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended) - * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic) - * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended) - * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic) - * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended) - * - * See also strftime(3) and ::strptime. + * strftime(format = '%FT%T%:z') -> string + * + * Returns a string representation of +self+, + * formatted according the given +format: + * + * DateTime.now.strftime # => "2022-07-01T11:03:19-05:00" + * + * For other formats, + * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]: + * */ static VALUE dt_lite_strftime(int argc, VALUE *argv, VALUE self) @@ -8529,6 +8999,47 @@ dt_lite_jisx0301(int argc, VALUE *argv, VALUE self) iso8601_timediv(self, n)); } +/* + * call-seq: + * deconstruct_keys(array_of_names_or_nil) -> hash + * + * Returns a hash of the name/value pairs, to use in pattern matching. + * Possible keys are: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, + * <tt>:wday</tt>, <tt>:yday</tt>, <tt>:hour</tt>, <tt>:min</tt>, + * <tt>:sec</tt>, <tt>:sec_fraction</tt>, <tt>:zone</tt>. + * + * Possible usages: + * + * dt = DateTime.new(2022, 10, 5, 13, 30) + * + * if d in wday: 1..5, hour: 10..18 # uses deconstruct_keys underneath + * puts "Working time" + * end + * #=> prints "Working time" + * + * case dt + * in year: ...2022 + * puts "too old" + * in month: ..9 + * puts "quarter 1-3" + * in wday: 1..5, month: + * puts "working day in month #{month}" + * end + * #=> prints "working day in month 10" + * + * Note that deconstruction by pattern can also be combined with class check: + * + * if d in DateTime(wday: 1..5, hour: 10..18, day: ..7) + * puts "Working time, first week of the month" + * end + * + */ +static VALUE +dt_lite_deconstruct_keys(VALUE self, VALUE keys) +{ + return deconstruct_keys(self, keys, /* is_datetime=true */ 1); +} + /* conversions */ #define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0) @@ -8607,7 +9118,7 @@ time_to_datetime(VALUE self) ret = d_complex_new_internal(cDateTime, nth, 0, 0, sf, - of, DEFAULT_SG, + of, GREGORIAN, ry, m, d, h, min, s, HAVE_CIVIL | HAVE_TIME); @@ -8620,33 +9131,43 @@ time_to_datetime(VALUE self) /* * call-seq: - * d.to_time -> time + * to_time -> time + * + * Returns a new Time object with the same value as +self+; + * if +self+ is a Julian date, derives its Gregorian date + * for conversion to the \Time object: + * + * Date.new(2001, 2, 3).to_time # => 2001-02-03 00:00:00 -0600 + * Date.new(2001, 2, 3, Date::JULIAN).to_time # => 2001-02-16 00:00:00 -0600 * - * Returns a Time object which denotes self. If self is a julian date, - * convert it to a gregorian date before converting it to Time. */ static VALUE date_to_time(VALUE self) { + VALUE t; + get_d1a(self); if (m_julian_p(adat)) { - VALUE tmp = d_lite_gregorian(self); - get_d1b(tmp); + VALUE g = d_lite_gregorian(self); + get_d1b(g); adat = bdat; + self = g; } - return f_local3(rb_cTime, + t = f_local3(rb_cTime, m_real_year(adat), INT2FIX(m_mon(adat)), INT2FIX(m_mday(adat))); + RB_GC_GUARD(self); /* may be the converted gregorian */ + return t; } /* * call-seq: - * d.to_date -> self + * to_date -> self * - * Returns self. + * Returns +self+. */ static VALUE date_to_date(VALUE self) @@ -8658,7 +9179,10 @@ date_to_date(VALUE self) * call-seq: * d.to_datetime -> datetime * - * Returns a DateTime object which denotes self. + * Returns a DateTime whose value is the same as +self+: + * + * Date.new(2001, 2, 3).to_datetime # => #<DateTime: 2001-02-03T00:00:00+00:00> + * */ static VALUE date_to_datetime(VALUE self) @@ -8703,12 +9227,18 @@ date_to_datetime(VALUE self) static VALUE datetime_to_time(VALUE self) { - volatile VALUE dup = dup_obj(self); + get_d1(self); + + if (m_julian_p(dat)) { + VALUE g = d_lite_gregorian(self); + get_d1a(g); + dat = adat; + self = g; + } + { VALUE t; - get_d1(dup); - t = rb_funcall(rb_cTime, rb_intern("new"), 7, @@ -8720,6 +9250,7 @@ datetime_to_time(VALUE self) f_add(INT2FIX(m_sec(dat)), m_sf_in_sec(dat)), INT2FIX(m_of(dat))); + RB_GC_GUARD(self); /* may be the converted gregorian */ return t; } } @@ -8776,6 +9307,7 @@ datetime_to_datetime(VALUE self) #define MIN_JD -327 #define MAX_JD 366963925 +/* :nodoc: */ static int test_civil(int from, int to, double sg) { @@ -8796,6 +9328,7 @@ test_civil(int from, int to, double sg) return 1; } +/* :nodoc: */ static VALUE date_s_test_civil(VALUE klass) { @@ -8816,6 +9349,7 @@ date_s_test_civil(VALUE klass) return Qtrue; } +/* :nodoc: */ static int test_ordinal(int from, int to, double sg) { @@ -8836,6 +9370,7 @@ test_ordinal(int from, int to, double sg) return 1; } +/* :nodoc: */ static VALUE date_s_test_ordinal(VALUE klass) { @@ -8856,6 +9391,7 @@ date_s_test_ordinal(VALUE klass) return Qtrue; } +/* :nodoc: */ static int test_commercial(int from, int to, double sg) { @@ -8876,6 +9412,7 @@ test_commercial(int from, int to, double sg) return 1; } +/* :nodoc: */ static VALUE date_s_test_commercial(VALUE klass) { @@ -8896,6 +9433,7 @@ date_s_test_commercial(VALUE klass) return Qtrue; } +/* :nodoc: */ static int test_weeknum(int from, int to, int f, double sg) { @@ -8916,6 +9454,7 @@ test_weeknum(int from, int to, int f, double sg) return 1; } +/* :nodoc: */ static VALUE date_s_test_weeknum(VALUE klass) { @@ -8940,6 +9479,7 @@ date_s_test_weeknum(VALUE klass) return Qtrue; } +/* :nodoc: */ static int test_nth_kday(int from, int to, double sg) { @@ -8960,6 +9500,7 @@ test_nth_kday(int from, int to, double sg) return 1; } +/* :nodoc: */ static VALUE date_s_test_nth_kday(VALUE klass) { @@ -8980,6 +9521,7 @@ date_s_test_nth_kday(VALUE klass) return Qtrue; } +/* :nodoc: */ static int test_unit_v2v(VALUE i, VALUE (* conv1)(VALUE), @@ -8991,6 +9533,7 @@ test_unit_v2v(VALUE i, return f_eqeq_p(o, i); } +/* :nodoc: */ static int test_unit_v2v_iter2(VALUE (* conv1)(VALUE), VALUE (* conv2)(VALUE)) @@ -9022,6 +9565,7 @@ test_unit_v2v_iter2(VALUE (* conv1)(VALUE), return 1; } +/* :nodoc: */ static int test_unit_v2v_iter(VALUE (* conv1)(VALUE), VALUE (* conv2)(VALUE)) @@ -9033,6 +9577,7 @@ test_unit_v2v_iter(VALUE (* conv1)(VALUE), return 1; } +/* :nodoc: */ static VALUE date_s_test_unit_conv(VALUE klass) { @@ -9047,6 +9592,7 @@ date_s_test_unit_conv(VALUE klass) return Qtrue; } +/* :nodoc: */ static VALUE date_s_test_all(VALUE klass) { @@ -9109,10 +9655,11 @@ mk_ary_of_str(long len, const char *a[]) } rb_ary_push(o, e); } - rb_obj_freeze(o); + rb_ary_freeze(o); return o; } +/* :nodoc: */ static VALUE d_lite_zero(VALUE x) { @@ -9130,7 +9677,19 @@ Init_date_core(void) id_ge_p = rb_intern_const(">="); id_eqeq_p = rb_intern_const("=="); + sym_year = ID2SYM(rb_intern_const("year")); + sym_month = ID2SYM(rb_intern_const("month")); + sym_yday = ID2SYM(rb_intern_const("yday")); + sym_wday = ID2SYM(rb_intern_const("wday")); + sym_day = ID2SYM(rb_intern_const("day")); + sym_hour = ID2SYM(rb_intern_const("hour")); + sym_min = ID2SYM(rb_intern_const("min")); + sym_sec = ID2SYM(rb_intern_const("sec")); + sym_sec_fraction = ID2SYM(rb_intern_const("sec_fraction")); + sym_zone = ID2SYM(rb_intern_const("zone")); + half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2)); + rb_gc_register_mark_object(half_days_in_day); #if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS * @@ -9142,160 +9701,87 @@ Init_date_core(void) day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS), INT2FIX(SECOND_IN_NANOSECONDS)); #endif - - rb_gc_register_mark_object(half_days_in_day); rb_gc_register_mark_object(day_in_nanoseconds); positive_inf = +INFINITY; negative_inf = -INFINITY; /* - * date and datetime class - Tadayoshi Funaba 1998-2011 - * - * 'date' provides two classes: Date and DateTime. + * \Class \Date provides methods for storing and manipulating + * calendar dates. * - * == Terms and Definitions + * Consider using + * {class Time}[rdoc-ref:Time] + * instead of class \Date if: * - * Some terms and definitions are based on ISO 8601 and JIS X 0301. + * - You need both dates and times; \Date handles only dates. + * - You need only Gregorian dates (and not Julian dates); + * see {Julian and Gregorian Calendars}[rdoc-ref:language/calendars.rdoc]. * - * === Calendar Date + * A \Date object, once created, is immutable, and cannot be modified. * - * The calendar date is a particular day of a calendar year, - * identified by its ordinal number within a calendar month within - * that year. + * == Creating a \Date * - * In those classes, this is so-called "civil". + * You can create a date for the current date, using Date.today: * - * === Ordinal Date + * Date.today # => #<Date: 1999-12-31> * - * The ordinal date is a particular day of a calendar year identified - * by its ordinal number within the year. + * You can create a specific date from various combinations of arguments: * - * In those classes, this is so-called "ordinal". + * - Date.new takes integer year, month, and day-of-month: * - * === Week Date + * Date.new(1999, 12, 31) # => #<Date: 1999-12-31> * - * The week date is a date identified by calendar week and day numbers. + * - Date.ordinal takes integer year and day-of-year: * - * The calendar week is a seven day period within a calendar year, - * starting on a Monday and identified by its ordinal number within - * the year; the first calendar week of the year is the one that - * includes the first Thursday of that year. In the Gregorian - * calendar, this is equivalent to the week which includes January 4. + * Date.ordinal(1999, 365) # => #<Date: 1999-12-31> * - * In those classes, this is so-called "commercial". + * - Date.jd takes integer Julian day: * - * === Julian Day Number + * Date.jd(2451544) # => #<Date: 1999-12-31> * - * The Julian day number is in elapsed days since noon (Greenwich Mean - * Time) on January 1, 4713 BCE (in the Julian calendar). + * - Date.commercial takes integer commercial data (year, week, day-of-week): * - * In this document, the astronomical Julian day number is the same as - * the original Julian day number. And the chronological Julian day - * number is a variation of the Julian day number. Its days begin at - * midnight on local time. + * Date.commercial(1999, 52, 5) # => #<Date: 1999-12-31> * - * In this document, when the term "Julian day number" simply appears, - * it just refers to "chronological Julian day number", not the - * original. + * - Date.parse takes a string, which it parses heuristically: * - * In those classes, those are so-called "ajd" and "jd". + * Date.parse('1999-12-31') # => #<Date: 1999-12-31> + * Date.parse('31-12-1999') # => #<Date: 1999-12-31> + * Date.parse('1999-365') # => #<Date: 1999-12-31> + * Date.parse('1999-W52-5') # => #<Date: 1999-12-31> * - * === Modified Julian Day Number + * - Date.strptime takes a date string and a format string, + * then parses the date string according to the format string: * - * The modified Julian day number is in elapsed days since midnight - * (Coordinated Universal Time) on November 17, 1858 CE (in the - * Gregorian calendar). + * Date.strptime('1999-12-31', '%Y-%m-%d') # => #<Date: 1999-12-31> + * Date.strptime('31-12-1999', '%d-%m-%Y') # => #<Date: 1999-12-31> + * Date.strptime('1999-365', '%Y-%j') # => #<Date: 1999-12-31> + * Date.strptime('1999-W52-5', '%G-W%V-%u') # => #<Date: 1999-12-31> + * Date.strptime('1999 52 5', '%Y %U %w') # => #<Date: 1999-12-31> + * Date.strptime('1999 52 5', '%Y %W %u') # => #<Date: 1999-12-31> + * Date.strptime('fri31dec99', '%a%d%b%y') # => #<Date: 1999-12-31> * - * In this document, the astronomical modified Julian day number is - * the same as the original modified Julian day number. And the - * chronological modified Julian day number is a variation of the - * modified Julian day number. Its days begin at midnight on local - * time. + * See also the specialized methods in + * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings] * - * In this document, when the term "modified Julian day number" simply - * appears, it just refers to "chronological modified Julian day - * number", not the original. + * == Argument +limit+ * - * In those classes, those are so-called "amjd" and "mjd". + * Certain singleton methods in \Date that parse string arguments + * also take optional keyword argument +limit+, + * which can limit the length of the string argument. * - * == Date + * When +limit+ is: * - * A subclass of Object that includes the Comparable module and - * easily handles date. - * - * A Date object is created with Date::new, Date::jd, Date::ordinal, - * Date::commercial, Date::parse, Date::strptime, Date::today, - * Time#to_date, etc. - * - * require 'date' - * - * Date.new(2001,2,3) - * #=> #<Date: 2001-02-03 ...> - * Date.jd(2451944) - * #=> #<Date: 2001-02-03 ...> - * Date.ordinal(2001,34) - * #=> #<Date: 2001-02-03 ...> - * Date.commercial(2001,5,6) - * #=> #<Date: 2001-02-03 ...> - * Date.parse('2001-02-03') - * #=> #<Date: 2001-02-03 ...> - * Date.strptime('03-02-2001', '%d-%m-%Y') - * #=> #<Date: 2001-02-03 ...> - * Time.new(2001,2,3).to_date - * #=> #<Date: 2001-02-03 ...> - * - * All date objects are immutable; hence cannot modify themselves. - * - * The concept of a date object can be represented as a tuple - * of the day count, the offset and the day of calendar reform. - * - * The day count denotes the absolute position of a temporal - * dimension. The offset is relative adjustment, which determines - * decoded local time with the day count. The day of calendar - * reform denotes the start day of the new style. The old style - * of the West is the Julian calendar which was adopted by - * Caesar. The new style is the Gregorian calendar, which is the - * current civil calendar of many countries. - * - * The day count is virtually the astronomical Julian day number. - * The offset in this class is usually zero, and cannot be - * specified directly. - * - * A Date object can be created with an optional argument, - * the day of calendar reform as a Julian day number, which - * should be 2298874 to 2426355 or negative/positive infinity. - * The default value is +Date::ITALY+ (2299161=1582-10-15). - * See also sample/cal.rb. - * - * $ ruby sample/cal.rb -c it 10 1582 - * October 1582 - * S M Tu W Th F S - * 1 2 3 4 15 16 - * 17 18 19 20 21 22 23 - * 24 25 26 27 28 29 30 - * 31 - * - * $ ruby sample/cal.rb -c gb 9 1752 - * September 1752 - * S M Tu W Th F S - * 1 2 14 15 16 - * 17 18 19 20 21 22 23 - * 24 25 26 27 28 29 30 - * - * A Date object has various methods. See each reference. - * - * d = Date.parse('3rd Feb 2001') - * #=> #<Date: 2001-02-03 ...> - * d.year #=> 2001 - * d.mon #=> 2 - * d.mday #=> 3 - * d.wday #=> 6 - * d += 1 #=> #<Date: 2001-02-04 ...> - * d.strftime('%a %d %b %Y') #=> "Sun 04 Feb 2001" + * - Non-negative: + * raises ArgumentError if the string length is greater than _limit_. + * - Other numeric or +nil+: ignores +limit+. + * - Other non-numeric: raises TypeError. * */ cDate = rb_define_class("Date", rb_cObject); + + /* Exception for invalid date/time */ eDateError = rb_define_class_under(cDate, "Error", rb_eArgError); rb_include_module(cDate, rb_mComparable); @@ -9403,19 +9889,19 @@ Init_date_core(void) rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1); rb_define_singleton_method(cDate, "_parse", date_s__parse, -1); rb_define_singleton_method(cDate, "parse", date_s_parse, -1); - rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1); + rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1); rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1); - rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1); + rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1); rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1); - rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1); + rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1); rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1); - rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1); - rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1); + rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1); + rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1); rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1); rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1); - rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1); + rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1); rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1); - rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1); + rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1); rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1); rb_define_method(cDate, "initialize", date_initialize, -1); @@ -9522,6 +10008,8 @@ Init_date_core(void) rb_define_method(cDate, "httpdate", d_lite_httpdate, 0); rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0); + rb_define_method(cDate, "deconstruct_keys", d_lite_deconstruct_keys, 1); + #ifndef NDEBUG rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0); #endif @@ -9732,6 +10220,8 @@ Init_date_core(void) rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1); rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1); + rb_define_method(cDateTime, "deconstruct_keys", dt_lite_deconstruct_keys, 1); + /* conversions */ rb_define_method(rb_cTime, "to_time", time_to_time, 0); diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c index 5fa036ed72..a1600e4708 100644 --- a/ext/date/date_parse.c +++ b/ext/date/date_parse.c @@ -7,6 +7,9 @@ #include "ruby/re.h" #include <ctype.h> +#undef strncasecmp +#define strncasecmp STRNCASECMP + RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y); RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow); @@ -253,6 +256,8 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc) #define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat" #define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec" +#define NUMBER "(?<!\\d)\\d" + #ifdef TIGHT_PARSER #define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?" #define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?" @@ -411,7 +416,6 @@ VALUE date_zone_to_diff(VALUE str) { VALUE offset = Qnil; - VALUE vbuf = 0; long l = RSTRING_LEN(str); const char *s = RSTRING_PTR(str); @@ -437,16 +441,26 @@ date_zone_to_diff(VALUE str) l -= w; dst = 1; } + { + const char *zn = s; long sl = shrunk_size(s, l); + char shrunk_buff[MAX_WORD_LENGTH]; /* no terminator to be added */ + const struct zone *z = 0; + + if (sl <= 0) { + sl = l; + } + else if (sl <= MAX_WORD_LENGTH) { + char *d = shrunk_buff; + sl = shrink_space(d, s, l); + zn = d; + } + if (sl > 0 && sl <= MAX_WORD_LENGTH) { - char *d = ALLOCV_N(char, vbuf, sl); - l = shrink_space(d, s, l); - s = d; + z = zonetab(zn, (unsigned int)sl); } - } - if (l > 0 && l <= MAX_WORD_LENGTH) { - const struct zone *z = zonetab(s, (unsigned int)l); + if (z) { int d = z->offset; if (dst) @@ -455,6 +469,7 @@ date_zone_to_diff(VALUE str) goto ok; } } + { char *p; int sign = 0; @@ -471,27 +486,53 @@ date_zone_to_diff(VALUE str) s++; l--; +#define out_of_range(v, min, max) ((v) < (min) || (max) < (v)) hour = STRTOUL(s, &p, 10); if (*p == ':') { + if (out_of_range(hour, 0, 23)) return Qnil; s = ++p; min = STRTOUL(s, &p, 10); + if (out_of_range(min, 0, 59)) return Qnil; if (*p == ':') { s = ++p; sec = STRTOUL(s, &p, 10); + if (out_of_range(sec, 0, 59)) return Qnil; } - goto num; } - if (*p == ',' || *p == '.') { - char *e = 0; - p++; - min = STRTOUL(p, &e, 10) * 3600; + else if (*p == ',' || *p == '.') { + /* fractional hour */ + size_t n; + int ov; + /* no over precision for offset; 10**-7 hour = 0.36 + * milliseconds should be enough. */ + const size_t max_digits = 7; /* 36 * 10**7 < 32-bit FIXNUM_MAX */ + + if (out_of_range(hour, 0, 23)) return Qnil; + + n = (s + l) - ++p; + if (n > max_digits) n = max_digits; + sec = ruby_scan_digits(p, n, 10, &n, &ov); + if ((p += n) < s + l && *p >= ('5' + !(sec & 1)) && *p <= '9') { + /* round half to even */ + sec++; + } + sec *= 36; if (sign) { hour = -hour; - min = -min; + sec = -sec; + } + if (n <= 2) { + /* HH.nn or HH.n */ + if (n == 1) sec *= 10; + offset = INT2FIX(sec + hour * 3600); + } + else { + VALUE denom = rb_int_positive_pow(10, (int)(n - 2)); + offset = f_add(rb_rational_new(INT2FIX(sec), denom), INT2FIX(hour * 3600)); + if (rb_rational_den(offset) == INT2FIX(1)) { + offset = rb_rational_num(offset); + } } - offset = rb_rational_new(INT2FIX(min), - rb_int_positive_pow(10, (int)(e - p))); - offset = f_add(INT2FIX(hour * 3600), offset); goto ok; } else if (l > 2) { @@ -504,18 +545,16 @@ date_zone_to_diff(VALUE str) min = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov); if (l >= 5) sec = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov); - goto num; } - num: sec += min * 60 + hour * 3600; if (sign) sec = -sec; offset = INT2FIX(sec); +#undef out_of_range } } } RB_GC_GUARD(str); ok: - ALLOCV_END(vbuf); return offset; } @@ -652,24 +691,27 @@ parse_time(VALUE str, VALUE hash) { static const char pat_source[] = "(" + "" NUMBER "+\\s*" "(?:" - "\\d+\\s*:\\s*\\d+" "(?:" + ":\\s*\\d+" + "(?:" #ifndef TIGHT_PARSER - "\\s*:\\s*\\d+(?:[,.]\\d*)?" + "\\s*:\\s*\\d+(?:[,.]\\d*)?" #else - "\\s*:\\s*\\d+(?:[,.]\\d+)?" + "\\s*:\\s*\\d+(?:[,.]\\d+)?" #endif + ")?" + "|" + "h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?" + ")" + "(?:" + "\\s*" + "[ap](?:m\\b|\\.m\\.)" ")?" "|" - "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?" - ")" - "(?:" - "\\s*" "[ap](?:m\\b|\\.m\\.)" - ")?" - "|" - "\\d+\\s*[ap](?:m\\b|\\.m\\.)" + ")" ")" "(?:" "\\s*" @@ -691,6 +733,9 @@ parse_time(VALUE str, VALUE hash) #endif } +#define BEGIN_ERA "\\b" +#define END_ERA "(?!(?<!\\.)[a-z])" + #ifdef TIGHT_PARSER static int parse_era1_cb(VALUE m, VALUE hash) @@ -702,7 +747,7 @@ static int parse_era1(VALUE str, VALUE hash) { static const char pat_source[] = - "(a(?:d|\\.d\\.))"; + BEGIN_ERA "(a(?:d\\b|\\.d\\.))" END_ERA; static VALUE pat = Qnil; REGCOMP_I(pat); @@ -724,8 +769,9 @@ parse_era2_cb(VALUE m, VALUE hash) static int parse_era2(VALUE str, VALUE hash) { - static const char pat_source[] = - "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))"; + static const char pat_source[] = BEGIN_ERA + "(c(?:e\\b|\\.e\\.)|b(?:ce\\b|\\.c\\.e\\.)|b(?:c\\b|\\.c\\.))" + END_ERA; static VALUE pat = Qnil; REGCOMP_I(pat); @@ -829,7 +875,7 @@ parse_eu(VALUE str, VALUE hash) FPW_COM FPT_COM #endif #ifndef TIGHT_PARSER - "('?\\d+)[^-\\d\\s]*" + "('?" NUMBER "+)[^-\\d\\s]*" #else "(\\d+)(?:(?:st|nd|rd|th)\\b)?" #endif @@ -842,7 +888,11 @@ parse_eu(VALUE str, VALUE hash) "(?:" "\\s*" #ifndef TIGHT_PARSER - "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?" + "(?:" + BEGIN_ERA + "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))" + END_ERA + ")?" "\\s*" "('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)" #else @@ -919,8 +969,8 @@ parse_us(VALUE str, VALUE hash) COM_FPT #endif "(?:" - "\\s*,?" - "\\s*" + "\\s*+,?" + "\\s*+" #ifndef TIGHT_PARSER "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?" "\\s*" @@ -967,7 +1017,7 @@ parse_iso(VALUE str, VALUE hash) { static const char pat_source[] = #ifndef TIGHT_PARSER - "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)" + "('?[-+]?" NUMBER "+)-(\\d+)-('?-?\\d+)" #else BOS FPW_COM FPT_COM @@ -1321,7 +1371,7 @@ parse_vms11(VALUE str, VALUE hash) { static const char pat_source[] = #ifndef TIGHT_PARSER - "('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*" + "('?-?" NUMBER "+)-(" ABBR_MONTHS ")[^-/.]*" "-('?-?\\d+)" #else BOS @@ -1416,7 +1466,7 @@ parse_sla(VALUE str, VALUE hash) { static const char pat_source[] = #ifndef TIGHT_PARSER - "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?" + "('?-?" NUMBER "+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?" #else BOS FPW_COM FPT_COM @@ -1524,7 +1574,7 @@ parse_dot(VALUE str, VALUE hash) { static const char pat_source[] = #ifndef TIGHT_PARSER - "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)" + "('?-?" NUMBER "+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)" #else BOS FPW_COM FPT_COM @@ -1684,7 +1734,7 @@ parse_mday(VALUE str, VALUE hash) { static const char pat_source[] = #ifndef TIGHT_PARSER - "(\\d+)(st|nd|rd|th)\\b" + "(" NUMBER "+)(st|nd|rd|th)\\b" #else BOS FPW_COM FPT_COM @@ -1922,7 +1972,7 @@ parse_ddd(VALUE str, VALUE hash) #ifdef TIGHT_PARSER BOS #endif - "([-+]?)(\\d{2,14})" + "([-+]?)(" NUMBER "{2,14})" "(?:" "\\s*" "t?" diff --git a/ext/date/date_strftime.c b/ext/date/date_strftime.c index 9d8167b612..d7f28989d6 100644 --- a/ext/date/date_strftime.c +++ b/ext/date/date_strftime.c @@ -393,7 +393,7 @@ date_strftime_with_tmx(char *s, const size_t maxsize, const char *format, continue; case 'v': - STRFTIME("%e-%b-%Y"); + STRFTIME("%e-%^b-%Y"); continue; case 'w': /* weekday, Sunday == 0, 0 - 6 */ diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c index 7b06a31471..1dde5fa3ec 100644 --- a/ext/date/date_strptime.c +++ b/ext/date/date_strptime.c @@ -7,31 +7,21 @@ #include "ruby/re.h" #include <ctype.h> +#undef strncasecmp +#define strncasecmp STRNCASECMP + static const char *day_names[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", - "Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat" }; +static const int ABBREVIATED_DAY_NAME_LENGTH = 3; static const char *month_names[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static const char *merid_names[] = { - "am", "pm", - "a.m.", "p.m." -}; - -static const char *extz_pats[] = { - ":z", - "::z", - ":::z" }; +static const int ABBREVIATED_MONTH_NAME_LENGTH = 3; #define sizeof_array(o) (sizeof o / sizeof o[0]) @@ -75,7 +65,7 @@ num_pattern_p(const char *s) #define NUM_PATTERN_P() num_pattern_p(&fmt[fi + 1]) static long -read_digits(const char *s, VALUE *n, size_t width) +read_digits(const char *s, size_t slen, VALUE *n, size_t width) { size_t l; @@ -83,7 +73,7 @@ read_digits(const char *s, VALUE *n, size_t width) return 0; l = 0; - while (ISDIGIT(s[l])) { + while (l < slen && ISDIGIT(s[l])) { if (++l == width) break; } @@ -131,9 +121,10 @@ do { \ #define READ_DIGITS(n,w) \ do { \ size_t l; \ - l = read_digits(&str[si], &n, w); \ - if (l == 0) \ + l = read_digits(&str[si], slen - si, &n, w); \ + if (l == 0) { \ fail(); \ + } \ si += l; \ } while (0) @@ -161,6 +152,12 @@ do { \ VALUE date_zone_to_diff(VALUE); +static inline int +head_match_p(size_t len, const char *name, const char *str, size_t slen, size_t si) +{ + return slen - si >= len && strncasecmp(name, &str[si], len) == 0; +} + static size_t date__strptime_internal(const char *str, size_t slen, const char *fmt, size_t flen, VALUE hash) @@ -168,9 +165,18 @@ date__strptime_internal(const char *str, size_t slen, size_t si, fi; int c; +#define HEAD_MATCH_P(len, name) head_match_p(len, name, str, slen, si) si = fi = 0; while (fi < flen) { + if (isspace((unsigned char)fmt[fi])) { + while (si < slen && isspace((unsigned char)str[si])) + si++; + while (++fi < flen && isspace((unsigned char)fmt[fi])); + continue; + } + + if (si >= slen) fail(); switch (fmt[fi]) { case '%': @@ -194,12 +200,11 @@ date__strptime_internal(const char *str, size_t slen, { int i; - for (i = 0; i < (int)sizeof_array(extz_pats); i++) - if (strncmp(extz_pats[i], &fmt[fi], - strlen(extz_pats[i])) == 0) { - fi += i; - goto again; - } + for (i = 1; i < 3 && fi + i < flen && fmt[fi+i] == ':'; ++i); + if (fmt[fi+i] == 'z') { + fi += i - 1; + goto again; + } fail(); } @@ -209,10 +214,12 @@ date__strptime_internal(const char *str, size_t slen, int i; for (i = 0; i < (int)sizeof_array(day_names); i++) { - size_t l = strlen(day_names[i]); - if (strncasecmp(day_names[i], &str[si], l) == 0) { + const char *day_name = day_names[i]; + size_t l = strlen(day_name); + if (HEAD_MATCH_P(l, day_name) || + HEAD_MATCH_P(l = ABBREVIATED_DAY_NAME_LENGTH, day_name)) { si += l; - set_hash("wday", INT2FIX(i % 7)); + set_hash("wday", INT2FIX(i)); goto matched; } } @@ -225,10 +232,12 @@ date__strptime_internal(const char *str, size_t slen, int i; for (i = 0; i < (int)sizeof_array(month_names); i++) { - size_t l = strlen(month_names[i]); - if (strncasecmp(month_names[i], &str[si], l) == 0) { + const char *month_name = month_names[i]; + size_t l = strlen(month_name); + if (HEAD_MATCH_P(l, month_name) || + HEAD_MATCH_P(l = ABBREVIATED_MONTH_NAME_LENGTH, month_name)) { si += l; - set_hash("mon", INT2FIX((i % 12) + 1)); + set_hash("mon", INT2FIX(i + 1)); goto matched; } } @@ -402,18 +411,19 @@ date__strptime_internal(const char *str, size_t slen, case 'P': case 'p': + if (slen - si < 2) fail(); { - int i; - - for (i = 0; i < 4; i++) { - size_t l = strlen(merid_names[i]); - if (strncasecmp(merid_names[i], &str[si], l) == 0) { - si += l; - set_hash("_merid", INT2FIX((i % 2) == 0 ? 0 : 12)); - goto matched; - } + char c = str[si]; + const int hour = (c == 'P' || c == 'p') ? 12 : 0; + if (!hour && !(c == 'A' || c == 'a')) fail(); + if ((c = str[si+1]) == '.') { + if (slen - si < 4 || str[si+3] != '.') fail(); + c = str[si += 2]; } - fail(); + if (!(c == 'M' || c == 'm')) fail(); + si += 2; + set_hash("_merid", INT2FIX(hour)); + goto matched; } case 'Q': @@ -587,7 +597,7 @@ date__strptime_internal(const char *str, size_t slen, b = rb_backref_get(); rb_match_busy(b); - m = f_match(pat, rb_usascii_str_new2(&str[si])); + m = f_match(pat, rb_usascii_str_new(&str[si], slen - si)); if (!NIL_P(m)) { VALUE s, l, o; @@ -619,22 +629,13 @@ date__strptime_internal(const char *str, size_t slen, if (str[si] != '%') fail(); si++; - if (fi < flen) - if (str[si] != fmt[fi]) + if (fi < flen) { + if (si >= slen || str[si] != fmt[fi]) fail(); - si++; + si++; + } goto matched; } - case ' ': - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - while (isspace((unsigned char)str[si])) - si++; - fi++; - break; default: ordinal: if (str[si] != fmt[fi]) @@ -660,6 +661,9 @@ date__strptime(const char *str, size_t slen, si = date__strptime_internal(str, slen, fmt, flen, hash); + if (fail_p()) + return Qnil; + if (slen > si) { VALUE s; @@ -667,9 +671,6 @@ date__strptime(const char *str, size_t slen, set_hash("leftover", s); } - if (fail_p()) - return Qnil; - cent = del_hash("_cent"); if (!NIL_P(cent)) { VALUE year; diff --git a/ext/date/depend b/ext/date/depend index c686530c70..4fb78149a1 100644 --- a/ext/date/depend +++ b/ext/date/depend @@ -2,6 +2,20 @@ date_core.o: $(RUBY_EXTCONF_H) date_core.o: $(arch_hdrdir)/ruby/config.h date_core.o: $(hdrdir)/ruby.h +date_core.o: $(hdrdir)/ruby/assert.h +date_core.o: $(hdrdir)/ruby/backward.h +date_core.o: $(hdrdir)/ruby/backward/2/assume.h +date_core.o: $(hdrdir)/ruby/backward/2/attributes.h +date_core.o: $(hdrdir)/ruby/backward/2/bool.h +date_core.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_core.o: $(hdrdir)/ruby/backward/2/limits.h +date_core.o: $(hdrdir)/ruby/backward/2/long_long.h +date_core.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_core.o: $(hdrdir)/ruby/backward/2/stdarg.h +date_core.o: $(hdrdir)/ruby/defines.h +date_core.o: $(hdrdir)/ruby/encoding.h +date_core.o: $(hdrdir)/ruby/intern.h +date_core.o: $(hdrdir)/ruby/internal/abi.h date_core.o: $(hdrdir)/ruby/internal/anyargs.h date_core.o: $(hdrdir)/ruby/internal/arithmetic.h date_core.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -39,6 +53,7 @@ date_core.o: $(hdrdir)/ruby/internal/attr/noexcept.h date_core.o: $(hdrdir)/ruby/internal/attr/noinline.h date_core.o: $(hdrdir)/ruby/internal/attr/nonnull.h date_core.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_core.o: $(hdrdir)/ruby/internal/attr/packed_struct.h date_core.o: $(hdrdir)/ruby/internal/attr/pure.h date_core.o: $(hdrdir)/ruby/internal/attr/restrict.h date_core.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -71,6 +86,15 @@ date_core.o: $(hdrdir)/ruby/internal/core/rtypeddata.h date_core.o: $(hdrdir)/ruby/internal/ctype.h date_core.o: $(hdrdir)/ruby/internal/dllexport.h date_core.o: $(hdrdir)/ruby/internal/dosish.h +date_core.o: $(hdrdir)/ruby/internal/encoding/coderange.h +date_core.o: $(hdrdir)/ruby/internal/encoding/ctype.h +date_core.o: $(hdrdir)/ruby/internal/encoding/encoding.h +date_core.o: $(hdrdir)/ruby/internal/encoding/pathname.h +date_core.o: $(hdrdir)/ruby/internal/encoding/re.h +date_core.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +date_core.o: $(hdrdir)/ruby/internal/encoding/string.h +date_core.o: $(hdrdir)/ruby/internal/encoding/symbol.h +date_core.o: $(hdrdir)/ruby/internal/encoding/transcode.h date_core.o: $(hdrdir)/ruby/internal/error.h date_core.o: $(hdrdir)/ruby/internal/eval.h date_core.o: $(hdrdir)/ruby/internal/event.h @@ -98,7 +122,6 @@ date_core.o: $(hdrdir)/ruby/internal/intern/enumerator.h date_core.o: $(hdrdir)/ruby/internal/intern/error.h date_core.o: $(hdrdir)/ruby/internal/intern/eval.h date_core.o: $(hdrdir)/ruby/internal/intern/file.h -date_core.o: $(hdrdir)/ruby/internal/intern/gc.h date_core.o: $(hdrdir)/ruby/internal/intern/hash.h date_core.o: $(hdrdir)/ruby/internal/intern/io.h date_core.o: $(hdrdir)/ruby/internal/intern/load.h @@ -115,6 +138,7 @@ date_core.o: $(hdrdir)/ruby/internal/intern/re.h date_core.o: $(hdrdir)/ruby/internal/intern/ruby.h date_core.o: $(hdrdir)/ruby/internal/intern/select.h date_core.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_core.o: $(hdrdir)/ruby/internal/intern/set.h date_core.o: $(hdrdir)/ruby/internal/intern/signal.h date_core.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_core.o: $(hdrdir)/ruby/internal/intern/string.h @@ -129,33 +153,18 @@ date_core.o: $(hdrdir)/ruby/internal/memory.h date_core.o: $(hdrdir)/ruby/internal/method.h date_core.o: $(hdrdir)/ruby/internal/module.h date_core.o: $(hdrdir)/ruby/internal/newobj.h -date_core.o: $(hdrdir)/ruby/internal/rgengc.h date_core.o: $(hdrdir)/ruby/internal/scan_args.h date_core.o: $(hdrdir)/ruby/internal/special_consts.h date_core.o: $(hdrdir)/ruby/internal/static_assert.h date_core.o: $(hdrdir)/ruby/internal/stdalign.h date_core.o: $(hdrdir)/ruby/internal/stdbool.h +date_core.o: $(hdrdir)/ruby/internal/stdckdint.h date_core.o: $(hdrdir)/ruby/internal/symbol.h -date_core.o: $(hdrdir)/ruby/internal/token_paste.h date_core.o: $(hdrdir)/ruby/internal/value.h date_core.o: $(hdrdir)/ruby/internal/value_type.h date_core.o: $(hdrdir)/ruby/internal/variable.h date_core.o: $(hdrdir)/ruby/internal/warning_push.h date_core.o: $(hdrdir)/ruby/internal/xmalloc.h -date_core.o: $(hdrdir)/ruby/assert.h -date_core.o: $(hdrdir)/ruby/backward.h -date_core.o: $(hdrdir)/ruby/backward/2/assume.h -date_core.o: $(hdrdir)/ruby/backward/2/attributes.h -date_core.o: $(hdrdir)/ruby/backward/2/bool.h -date_core.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h -date_core.o: $(hdrdir)/ruby/backward/2/inttypes.h -date_core.o: $(hdrdir)/ruby/backward/2/limits.h -date_core.o: $(hdrdir)/ruby/backward/2/long_long.h -date_core.o: $(hdrdir)/ruby/backward/2/stdalign.h -date_core.o: $(hdrdir)/ruby/backward/2/stdarg.h -date_core.o: $(hdrdir)/ruby/defines.h -date_core.o: $(hdrdir)/ruby/encoding.h -date_core.o: $(hdrdir)/ruby/intern.h date_core.o: $(hdrdir)/ruby/missing.h date_core.o: $(hdrdir)/ruby/onigmo.h date_core.o: $(hdrdir)/ruby/oniguruma.h @@ -168,6 +177,20 @@ date_core.o: date_tmx.h date_parse.o: $(RUBY_EXTCONF_H) date_parse.o: $(arch_hdrdir)/ruby/config.h date_parse.o: $(hdrdir)/ruby.h +date_parse.o: $(hdrdir)/ruby/assert.h +date_parse.o: $(hdrdir)/ruby/backward.h +date_parse.o: $(hdrdir)/ruby/backward/2/assume.h +date_parse.o: $(hdrdir)/ruby/backward/2/attributes.h +date_parse.o: $(hdrdir)/ruby/backward/2/bool.h +date_parse.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_parse.o: $(hdrdir)/ruby/backward/2/limits.h +date_parse.o: $(hdrdir)/ruby/backward/2/long_long.h +date_parse.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_parse.o: $(hdrdir)/ruby/backward/2/stdarg.h +date_parse.o: $(hdrdir)/ruby/defines.h +date_parse.o: $(hdrdir)/ruby/encoding.h +date_parse.o: $(hdrdir)/ruby/intern.h +date_parse.o: $(hdrdir)/ruby/internal/abi.h date_parse.o: $(hdrdir)/ruby/internal/anyargs.h date_parse.o: $(hdrdir)/ruby/internal/arithmetic.h date_parse.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -205,6 +228,7 @@ date_parse.o: $(hdrdir)/ruby/internal/attr/noexcept.h date_parse.o: $(hdrdir)/ruby/internal/attr/noinline.h date_parse.o: $(hdrdir)/ruby/internal/attr/nonnull.h date_parse.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_parse.o: $(hdrdir)/ruby/internal/attr/packed_struct.h date_parse.o: $(hdrdir)/ruby/internal/attr/pure.h date_parse.o: $(hdrdir)/ruby/internal/attr/restrict.h date_parse.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -238,6 +262,15 @@ date_parse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h date_parse.o: $(hdrdir)/ruby/internal/ctype.h date_parse.o: $(hdrdir)/ruby/internal/dllexport.h date_parse.o: $(hdrdir)/ruby/internal/dosish.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/coderange.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/ctype.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/encoding.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/pathname.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/re.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/string.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/symbol.h +date_parse.o: $(hdrdir)/ruby/internal/encoding/transcode.h date_parse.o: $(hdrdir)/ruby/internal/error.h date_parse.o: $(hdrdir)/ruby/internal/eval.h date_parse.o: $(hdrdir)/ruby/internal/event.h @@ -265,7 +298,6 @@ date_parse.o: $(hdrdir)/ruby/internal/intern/enumerator.h date_parse.o: $(hdrdir)/ruby/internal/intern/error.h date_parse.o: $(hdrdir)/ruby/internal/intern/eval.h date_parse.o: $(hdrdir)/ruby/internal/intern/file.h -date_parse.o: $(hdrdir)/ruby/internal/intern/gc.h date_parse.o: $(hdrdir)/ruby/internal/intern/hash.h date_parse.o: $(hdrdir)/ruby/internal/intern/io.h date_parse.o: $(hdrdir)/ruby/internal/intern/load.h @@ -282,6 +314,7 @@ date_parse.o: $(hdrdir)/ruby/internal/intern/re.h date_parse.o: $(hdrdir)/ruby/internal/intern/ruby.h date_parse.o: $(hdrdir)/ruby/internal/intern/select.h date_parse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_parse.o: $(hdrdir)/ruby/internal/intern/set.h date_parse.o: $(hdrdir)/ruby/internal/intern/signal.h date_parse.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_parse.o: $(hdrdir)/ruby/internal/intern/string.h @@ -296,33 +329,18 @@ date_parse.o: $(hdrdir)/ruby/internal/memory.h date_parse.o: $(hdrdir)/ruby/internal/method.h date_parse.o: $(hdrdir)/ruby/internal/module.h date_parse.o: $(hdrdir)/ruby/internal/newobj.h -date_parse.o: $(hdrdir)/ruby/internal/rgengc.h date_parse.o: $(hdrdir)/ruby/internal/scan_args.h date_parse.o: $(hdrdir)/ruby/internal/special_consts.h date_parse.o: $(hdrdir)/ruby/internal/static_assert.h date_parse.o: $(hdrdir)/ruby/internal/stdalign.h date_parse.o: $(hdrdir)/ruby/internal/stdbool.h +date_parse.o: $(hdrdir)/ruby/internal/stdckdint.h date_parse.o: $(hdrdir)/ruby/internal/symbol.h -date_parse.o: $(hdrdir)/ruby/internal/token_paste.h date_parse.o: $(hdrdir)/ruby/internal/value.h date_parse.o: $(hdrdir)/ruby/internal/value_type.h date_parse.o: $(hdrdir)/ruby/internal/variable.h date_parse.o: $(hdrdir)/ruby/internal/warning_push.h date_parse.o: $(hdrdir)/ruby/internal/xmalloc.h -date_parse.o: $(hdrdir)/ruby/assert.h -date_parse.o: $(hdrdir)/ruby/backward.h -date_parse.o: $(hdrdir)/ruby/backward/2/assume.h -date_parse.o: $(hdrdir)/ruby/backward/2/attributes.h -date_parse.o: $(hdrdir)/ruby/backward/2/bool.h -date_parse.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h -date_parse.o: $(hdrdir)/ruby/backward/2/inttypes.h -date_parse.o: $(hdrdir)/ruby/backward/2/limits.h -date_parse.o: $(hdrdir)/ruby/backward/2/long_long.h -date_parse.o: $(hdrdir)/ruby/backward/2/stdalign.h -date_parse.o: $(hdrdir)/ruby/backward/2/stdarg.h -date_parse.o: $(hdrdir)/ruby/defines.h -date_parse.o: $(hdrdir)/ruby/encoding.h -date_parse.o: $(hdrdir)/ruby/intern.h date_parse.o: $(hdrdir)/ruby/missing.h date_parse.o: $(hdrdir)/ruby/onigmo.h date_parse.o: $(hdrdir)/ruby/oniguruma.h @@ -336,6 +354,19 @@ date_parse.o: zonetab.h date_parse.o: zonetab.list date_strftime.o: $(RUBY_EXTCONF_H) date_strftime.o: $(arch_hdrdir)/ruby/config.h +date_strftime.o: $(hdrdir)/ruby/assert.h +date_strftime.o: $(hdrdir)/ruby/backward.h +date_strftime.o: $(hdrdir)/ruby/backward/2/assume.h +date_strftime.o: $(hdrdir)/ruby/backward/2/attributes.h +date_strftime.o: $(hdrdir)/ruby/backward/2/bool.h +date_strftime.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_strftime.o: $(hdrdir)/ruby/backward/2/limits.h +date_strftime.o: $(hdrdir)/ruby/backward/2/long_long.h +date_strftime.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_strftime.o: $(hdrdir)/ruby/backward/2/stdarg.h +date_strftime.o: $(hdrdir)/ruby/defines.h +date_strftime.o: $(hdrdir)/ruby/intern.h +date_strftime.o: $(hdrdir)/ruby/internal/abi.h date_strftime.o: $(hdrdir)/ruby/internal/anyargs.h date_strftime.o: $(hdrdir)/ruby/internal/arithmetic.h date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -373,6 +404,7 @@ date_strftime.o: $(hdrdir)/ruby/internal/attr/noexcept.h date_strftime.o: $(hdrdir)/ruby/internal/attr/noinline.h date_strftime.o: $(hdrdir)/ruby/internal/attr/nonnull.h date_strftime.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_strftime.o: $(hdrdir)/ruby/internal/attr/packed_struct.h date_strftime.o: $(hdrdir)/ruby/internal/attr/pure.h date_strftime.o: $(hdrdir)/ruby/internal/attr/restrict.h date_strftime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -432,7 +464,6 @@ date_strftime.o: $(hdrdir)/ruby/internal/intern/enumerator.h date_strftime.o: $(hdrdir)/ruby/internal/intern/error.h date_strftime.o: $(hdrdir)/ruby/internal/intern/eval.h date_strftime.o: $(hdrdir)/ruby/internal/intern/file.h -date_strftime.o: $(hdrdir)/ruby/internal/intern/gc.h date_strftime.o: $(hdrdir)/ruby/internal/intern/hash.h date_strftime.o: $(hdrdir)/ruby/internal/intern/io.h date_strftime.o: $(hdrdir)/ruby/internal/intern/load.h @@ -449,6 +480,7 @@ date_strftime.o: $(hdrdir)/ruby/internal/intern/re.h date_strftime.o: $(hdrdir)/ruby/internal/intern/ruby.h date_strftime.o: $(hdrdir)/ruby/internal/intern/select.h date_strftime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/set.h date_strftime.o: $(hdrdir)/ruby/internal/intern/signal.h date_strftime.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_strftime.o: $(hdrdir)/ruby/internal/intern/string.h @@ -463,32 +495,18 @@ date_strftime.o: $(hdrdir)/ruby/internal/memory.h date_strftime.o: $(hdrdir)/ruby/internal/method.h date_strftime.o: $(hdrdir)/ruby/internal/module.h date_strftime.o: $(hdrdir)/ruby/internal/newobj.h -date_strftime.o: $(hdrdir)/ruby/internal/rgengc.h date_strftime.o: $(hdrdir)/ruby/internal/scan_args.h date_strftime.o: $(hdrdir)/ruby/internal/special_consts.h date_strftime.o: $(hdrdir)/ruby/internal/static_assert.h date_strftime.o: $(hdrdir)/ruby/internal/stdalign.h date_strftime.o: $(hdrdir)/ruby/internal/stdbool.h +date_strftime.o: $(hdrdir)/ruby/internal/stdckdint.h date_strftime.o: $(hdrdir)/ruby/internal/symbol.h -date_strftime.o: $(hdrdir)/ruby/internal/token_paste.h date_strftime.o: $(hdrdir)/ruby/internal/value.h date_strftime.o: $(hdrdir)/ruby/internal/value_type.h date_strftime.o: $(hdrdir)/ruby/internal/variable.h date_strftime.o: $(hdrdir)/ruby/internal/warning_push.h date_strftime.o: $(hdrdir)/ruby/internal/xmalloc.h -date_strftime.o: $(hdrdir)/ruby/assert.h -date_strftime.o: $(hdrdir)/ruby/backward.h -date_strftime.o: $(hdrdir)/ruby/backward/2/assume.h -date_strftime.o: $(hdrdir)/ruby/backward/2/attributes.h -date_strftime.o: $(hdrdir)/ruby/backward/2/bool.h -date_strftime.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h -date_strftime.o: $(hdrdir)/ruby/backward/2/inttypes.h -date_strftime.o: $(hdrdir)/ruby/backward/2/limits.h -date_strftime.o: $(hdrdir)/ruby/backward/2/long_long.h -date_strftime.o: $(hdrdir)/ruby/backward/2/stdalign.h -date_strftime.o: $(hdrdir)/ruby/backward/2/stdarg.h -date_strftime.o: $(hdrdir)/ruby/defines.h -date_strftime.o: $(hdrdir)/ruby/intern.h date_strftime.o: $(hdrdir)/ruby/missing.h date_strftime.o: $(hdrdir)/ruby/ruby.h date_strftime.o: $(hdrdir)/ruby/st.h @@ -498,6 +516,20 @@ date_strftime.o: date_tmx.h date_strptime.o: $(RUBY_EXTCONF_H) date_strptime.o: $(arch_hdrdir)/ruby/config.h date_strptime.o: $(hdrdir)/ruby.h +date_strptime.o: $(hdrdir)/ruby/assert.h +date_strptime.o: $(hdrdir)/ruby/backward.h +date_strptime.o: $(hdrdir)/ruby/backward/2/assume.h +date_strptime.o: $(hdrdir)/ruby/backward/2/attributes.h +date_strptime.o: $(hdrdir)/ruby/backward/2/bool.h +date_strptime.o: $(hdrdir)/ruby/backward/2/inttypes.h +date_strptime.o: $(hdrdir)/ruby/backward/2/limits.h +date_strptime.o: $(hdrdir)/ruby/backward/2/long_long.h +date_strptime.o: $(hdrdir)/ruby/backward/2/stdalign.h +date_strptime.o: $(hdrdir)/ruby/backward/2/stdarg.h +date_strptime.o: $(hdrdir)/ruby/defines.h +date_strptime.o: $(hdrdir)/ruby/encoding.h +date_strptime.o: $(hdrdir)/ruby/intern.h +date_strptime.o: $(hdrdir)/ruby/internal/abi.h date_strptime.o: $(hdrdir)/ruby/internal/anyargs.h date_strptime.o: $(hdrdir)/ruby/internal/arithmetic.h date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -535,6 +567,7 @@ date_strptime.o: $(hdrdir)/ruby/internal/attr/noexcept.h date_strptime.o: $(hdrdir)/ruby/internal/attr/noinline.h date_strptime.o: $(hdrdir)/ruby/internal/attr/nonnull.h date_strptime.o: $(hdrdir)/ruby/internal/attr/noreturn.h +date_strptime.o: $(hdrdir)/ruby/internal/attr/packed_struct.h date_strptime.o: $(hdrdir)/ruby/internal/attr/pure.h date_strptime.o: $(hdrdir)/ruby/internal/attr/restrict.h date_strptime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -568,6 +601,15 @@ date_strptime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h date_strptime.o: $(hdrdir)/ruby/internal/ctype.h date_strptime.o: $(hdrdir)/ruby/internal/dllexport.h date_strptime.o: $(hdrdir)/ruby/internal/dosish.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/coderange.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/ctype.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/encoding.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/pathname.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/re.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/string.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/symbol.h +date_strptime.o: $(hdrdir)/ruby/internal/encoding/transcode.h date_strptime.o: $(hdrdir)/ruby/internal/error.h date_strptime.o: $(hdrdir)/ruby/internal/eval.h date_strptime.o: $(hdrdir)/ruby/internal/event.h @@ -595,7 +637,6 @@ date_strptime.o: $(hdrdir)/ruby/internal/intern/enumerator.h date_strptime.o: $(hdrdir)/ruby/internal/intern/error.h date_strptime.o: $(hdrdir)/ruby/internal/intern/eval.h date_strptime.o: $(hdrdir)/ruby/internal/intern/file.h -date_strptime.o: $(hdrdir)/ruby/internal/intern/gc.h date_strptime.o: $(hdrdir)/ruby/internal/intern/hash.h date_strptime.o: $(hdrdir)/ruby/internal/intern/io.h date_strptime.o: $(hdrdir)/ruby/internal/intern/load.h @@ -612,6 +653,7 @@ date_strptime.o: $(hdrdir)/ruby/internal/intern/re.h date_strptime.o: $(hdrdir)/ruby/internal/intern/ruby.h date_strptime.o: $(hdrdir)/ruby/internal/intern/select.h date_strptime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/set.h date_strptime.o: $(hdrdir)/ruby/internal/intern/signal.h date_strptime.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_strptime.o: $(hdrdir)/ruby/internal/intern/string.h @@ -626,33 +668,18 @@ date_strptime.o: $(hdrdir)/ruby/internal/memory.h date_strptime.o: $(hdrdir)/ruby/internal/method.h date_strptime.o: $(hdrdir)/ruby/internal/module.h date_strptime.o: $(hdrdir)/ruby/internal/newobj.h -date_strptime.o: $(hdrdir)/ruby/internal/rgengc.h date_strptime.o: $(hdrdir)/ruby/internal/scan_args.h date_strptime.o: $(hdrdir)/ruby/internal/special_consts.h date_strptime.o: $(hdrdir)/ruby/internal/static_assert.h date_strptime.o: $(hdrdir)/ruby/internal/stdalign.h date_strptime.o: $(hdrdir)/ruby/internal/stdbool.h +date_strptime.o: $(hdrdir)/ruby/internal/stdckdint.h date_strptime.o: $(hdrdir)/ruby/internal/symbol.h -date_strptime.o: $(hdrdir)/ruby/internal/token_paste.h date_strptime.o: $(hdrdir)/ruby/internal/value.h date_strptime.o: $(hdrdir)/ruby/internal/value_type.h date_strptime.o: $(hdrdir)/ruby/internal/variable.h date_strptime.o: $(hdrdir)/ruby/internal/warning_push.h date_strptime.o: $(hdrdir)/ruby/internal/xmalloc.h -date_strptime.o: $(hdrdir)/ruby/assert.h -date_strptime.o: $(hdrdir)/ruby/backward.h -date_strptime.o: $(hdrdir)/ruby/backward/2/assume.h -date_strptime.o: $(hdrdir)/ruby/backward/2/attributes.h -date_strptime.o: $(hdrdir)/ruby/backward/2/bool.h -date_strptime.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h -date_strptime.o: $(hdrdir)/ruby/backward/2/inttypes.h -date_strptime.o: $(hdrdir)/ruby/backward/2/limits.h -date_strptime.o: $(hdrdir)/ruby/backward/2/long_long.h -date_strptime.o: $(hdrdir)/ruby/backward/2/stdalign.h -date_strptime.o: $(hdrdir)/ruby/backward/2/stdarg.h -date_strptime.o: $(hdrdir)/ruby/defines.h -date_strptime.o: $(hdrdir)/ruby/encoding.h -date_strptime.o: $(hdrdir)/ruby/intern.h date_strptime.o: $(hdrdir)/ruby/missing.h date_strptime.o: $(hdrdir)/ruby/onigmo.h date_strptime.o: $(hdrdir)/ruby/oniguruma.h diff --git a/ext/date/extconf.rb b/ext/date/extconf.rb index 8938df13b3..8a1467df09 100644 --- a/ext/date/extconf.rb +++ b/ext/date/extconf.rb @@ -3,7 +3,11 @@ require 'mkmf' config_string("strict_warnflags") {|w| $warnflags += " #{w}"} -have_var("timezone", "time.h") -have_var("altzone", "time.h") +append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7." +have_func("rb_category_warn") +with_werror("", {:werror => true}) do |opt, | + have_var("timezone", "time.h", opt) + have_var("altzone", "time.h", opt) +end create_makefile('date_core') diff --git a/ext/date/lib/date.rb b/ext/date/lib/date.rb index 65c34ace49..0cb763017f 100644 --- a/ext/date/lib/date.rb +++ b/ext/date/lib/date.rb @@ -4,7 +4,12 @@ require 'date_core' class Date + VERSION = "3.5.1" # :nodoc: + # call-seq: + # infinite? -> false + # + # Returns +false+ def infinite? false end @@ -30,6 +35,8 @@ class Date def <=>(other) case other when Infinity; return d <=> other.d + when Float::INFINITY; return d <=> 1 + when -Float::INFINITY; return d <=> -1 when Numeric; return d else begin diff --git a/ext/date/prereq.mk b/ext/date/prereq.mk index eb71e55e71..b5d271a32c 100644 --- a/ext/date/prereq.mk +++ b/ext/date/prereq.mk @@ -1,7 +1,7 @@ .SUFFIXES: .list .list.h: - gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \ + gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \ | sed -f $(top_srcdir)/tool/gperf.sed \ > $(@F) @@ -10,3 +10,10 @@ zonetab.h: zonetab.list .PHONY: update-zonetab update-zonetab: $(RUBY) -C $(srcdir) update-abbr + +.PHONY: update-nothing +update-nothing: + +update = nothing + +zonetab.list: update-$(update) diff --git a/ext/date/zonetab.h b/ext/date/zonetab.h index 379f78e1b8..2a2e8910c9 100644 --- a/ext/date/zonetab.h +++ b/ext/date/zonetab.h @@ -1,5 +1,5 @@ /* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */ +/* Command-line: gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */ /* Computed positions: -k'1-4,9' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -29,15 +29,17 @@ #error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>." #endif -#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n) #line 1 "zonetab.list" +#define GPERF_DOWNCASE 1 +#define GPERF_CASE_STRNCMP 1 +#define gperf_case_strncmp strncasecmp struct zone { int name; int offset; }; -static const struct zone *zonetab(); -#line 9 "zonetab.list" +static const struct zone *zonetab(register const char *str, register size_t len); +#line 12 "zonetab.list" struct zone; #define TOTAL_KEYWORDS 316 @@ -808,736 +810,736 @@ zonetab (register const char *str, register size_t len) static const struct zone wordlist[] = { {-1}, {-1}, -#line 34 "zonetab.list" - {gperf_offsetof(stringpool, 2), -2*3600}, -#line 43 "zonetab.list" - {gperf_offsetof(stringpool, 3), -11*3600}, -#line 45 "zonetab.list" - {gperf_offsetof(stringpool, 4), 0*3600}, -#line 36 "zonetab.list" - {gperf_offsetof(stringpool, 5), -4*3600}, - {-1}, {-1}, -#line 269 "zonetab.list" - {gperf_offsetof(stringpool, 8),21600}, -#line 268 "zonetab.list" - {gperf_offsetof(stringpool, 9),25200}, -#line 35 "zonetab.list" - {gperf_offsetof(stringpool, 10), -3*3600}, +#line 37 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str2, -2*3600}, +#line 46 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str3, -11*3600}, +#line 48 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str4, 0*3600}, +#line 39 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str5, -4*3600}, {-1}, {-1}, -#line 21 "zonetab.list" - {gperf_offsetof(stringpool, 13), 1*3600}, -#line 25 "zonetab.list" - {gperf_offsetof(stringpool, 14), 5*3600}, -#line 271 "zonetab.list" - {gperf_offsetof(stringpool, 15),-18000}, -#line 279 "zonetab.list" - {gperf_offsetof(stringpool, 16),-10800}, -#line 273 "zonetab.list" - {gperf_offsetof(stringpool, 17),43200}, #line 272 "zonetab.list" - {gperf_offsetof(stringpool, 18),43200}, -#line 80 "zonetab.list" - {gperf_offsetof(stringpool, 19), 2*3600}, -#line 186 "zonetab.list" - {gperf_offsetof(stringpool, 20),36000}, -#line 88 "zonetab.list" - {gperf_offsetof(stringpool, 21), 3*3600}, -#line 87 "zonetab.list" - {gperf_offsetof(stringpool, 22), 3*3600}, - {-1}, -#line 101 "zonetab.list" - {gperf_offsetof(stringpool, 24),10*3600}, -#line 217 "zonetab.list" - {gperf_offsetof(stringpool, 25),-18000}, -#line 19 "zonetab.list" - {gperf_offsetof(stringpool, 26), -8*3600}, -#line 133 "zonetab.list" - {gperf_offsetof(stringpool, 27), -18000}, -#line 32 "zonetab.list" - {gperf_offsetof(stringpool, 28), 12*3600}, -#line 56 "zonetab.list" - {gperf_offsetof(stringpool, 29), -4*3600}, -#line 13 "zonetab.list" - {gperf_offsetof(stringpool, 30), -5*3600}, -#line 23 "zonetab.list" - {gperf_offsetof(stringpool, 31), 3*3600}, -#line 256 "zonetab.list" - {gperf_offsetof(stringpool, 32),23400}, -#line 73 "zonetab.list" - {gperf_offsetof(stringpool, 33), 1*3600}, - {-1}, -#line 82 "zonetab.list" - {gperf_offsetof(stringpool, 35), 2*3600}, -#line 71 "zonetab.list" - {gperf_offsetof(stringpool, 36), 1*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str8,21600}, +#line 271 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str9,25200}, +#line 38 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str10, -3*3600}, + {-1}, {-1}, #line 24 "zonetab.list" - {gperf_offsetof(stringpool, 37), 4*3600}, -#line 79 "zonetab.list" - {gperf_offsetof(stringpool, 38), 2*3600}, -#line 65 "zonetab.list" - {gperf_offsetof(stringpool, 39),-10*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, 1*3600}, +#line 28 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, 5*3600}, +#line 274 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15,-18000}, +#line 282 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16,-10800}, +#line 276 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17,43200}, +#line 275 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18,43200}, +#line 83 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, 2*3600}, +#line 189 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20,36000}, +#line 91 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, 3*3600}, +#line 90 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, 3*3600}, {-1}, -#line 202 "zonetab.list" - {gperf_offsetof(stringpool, 41),28800}, -#line 252 "zonetab.list" - {gperf_offsetof(stringpool, 42),39600}, -#line 251 "zonetab.list" - {gperf_offsetof(stringpool, 43),43200}, -#line 17 "zonetab.list" - {gperf_offsetof(stringpool, 44), -7*3600}, -#line 89 "zonetab.list" - {gperf_offsetof(stringpool, 45), 3*3600}, -#line 212 "zonetab.list" - {gperf_offsetof(stringpool, 46),-18000}, -#line 15 "zonetab.list" - {gperf_offsetof(stringpool, 47), -6*3600}, -#line 192 "zonetab.list" - {gperf_offsetof(stringpool, 48),18000}, -#line 26 "zonetab.list" - {gperf_offsetof(stringpool, 49), 6*3600}, - {-1}, {-1}, -#line 51 "zonetab.list" - {gperf_offsetof(stringpool, 52), -3*3600}, -#line 226 "zonetab.list" - {gperf_offsetof(stringpool, 53),-7200}, -#line 221 "zonetab.list" - {gperf_offsetof(stringpool, 54),10800}, +#line 104 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24,-6*3600}, +#line 220 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25,-18000}, #line 22 "zonetab.list" - {gperf_offsetof(stringpool, 55), 2*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, -8*3600}, +#line 136 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str27, -18000}, +#line 35 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, 12*3600}, +#line 59 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, -4*3600}, +#line 16 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, -5*3600}, +#line 26 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, 3*3600}, +#line 259 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32,23400}, +#line 76 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, 1*3600}, {-1}, -#line 190 "zonetab.list" - {gperf_offsetof(stringpool, 57),43200}, -#line 189 "zonetab.list" - {gperf_offsetof(stringpool, 58),43200}, -#line 199 "zonetab.list" - {gperf_offsetof(stringpool, 59),28800}, -#line 29 "zonetab.list" - {gperf_offsetof(stringpool, 60), 9*3600}, -#line 276 "zonetab.list" - {gperf_offsetof(stringpool, 61),28800}, -#line 48 "zonetab.list" - {gperf_offsetof(stringpool, 62), -2*3600}, -#line 94 "zonetab.list" - {gperf_offsetof(stringpool, 63), 6*3600}, +#line 85 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, 2*3600}, #line 74 "zonetab.list" - {gperf_offsetof(stringpool, 64), 1*3600}, -#line 81 "zonetab.list" - {gperf_offsetof(stringpool, 65), 2*3600}, -#line 64 "zonetab.list" - {gperf_offsetof(stringpool, 66),-10*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, 1*3600}, +#line 27 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, 4*3600}, +#line 82 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, 2*3600}, +#line 68 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39,2*3600}, + {-1}, +#line 205 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41,28800}, +#line 255 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42,39600}, #line 254 "zonetab.list" - {gperf_offsetof(stringpool, 67),18000}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43,43200}, +#line 20 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, -7*3600}, #line 92 "zonetab.list" - {gperf_offsetof(stringpool, 68), 5*3600}, - {-1}, -#line 200 "zonetab.list" - {gperf_offsetof(stringpool, 70),-14400}, -#line 70 "zonetab.list" - {gperf_offsetof(stringpool, 71), 1*3600}, -#line 281 "zonetab.list" - {gperf_offsetof(stringpool, 72),32400}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, 3*3600}, +#line 215 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46,-18000}, +#line 18 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, -6*3600}, +#line 195 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48,18000}, +#line 29 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, 6*3600}, + {-1}, {-1}, +#line 54 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, -3*3600}, +#line 229 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53,-7200}, +#line 224 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54,10800}, +#line 25 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str55, 2*3600}, {-1}, -#line 280 "zonetab.list" - {gperf_offsetof(stringpool, 74),39600}, -#line 238 "zonetab.list" - {gperf_offsetof(stringpool, 75),21600}, -#line 93 "zonetab.list" - {gperf_offsetof(stringpool, 76), (5*3600+1800)}, -#line 194 "zonetab.list" - {gperf_offsetof(stringpool, 77),28800}, +#line 193 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57,43200}, +#line 192 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str58,43200}, +#line 202 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str59,28800}, +#line 32 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, 9*3600}, +#line 279 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61,28800}, +#line 51 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, -2*3600}, +#line 97 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, 6*3600}, +#line 77 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, 1*3600}, +#line 84 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, 2*3600}, +#line 67 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66,-10*3600}, +#line 257 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67,18000}, +#line 95 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str68, 5*3600}, {-1}, -#line 255 "zonetab.list" - {gperf_offsetof(stringpool, 79),43200}, -#line 75 "zonetab.list" - {gperf_offsetof(stringpool, 80), 1*3600}, -#line 270 "zonetab.list" - {gperf_offsetof(stringpool, 81),18000}, -#line 83 "zonetab.list" - {gperf_offsetof(stringpool, 82), 2*3600}, +#line 203 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str70,-14400}, +#line 73 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, 1*3600}, +#line 284 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72,32400}, {-1}, -#line 207 "zonetab.list" - {gperf_offsetof(stringpool, 84),36000}, -#line 278 "zonetab.list" - {gperf_offsetof(stringpool, 85),-7200}, - {-1}, {-1}, -#line 126 "zonetab.list" - {gperf_offsetof(stringpool, 88), -21600}, -#line 185 "zonetab.list" - {gperf_offsetof(stringpool, 89),39600}, -#line 183 "zonetab.list" - {gperf_offsetof(stringpool, 90),-18000}, -#line 218 "zonetab.list" - {gperf_offsetof(stringpool, 91),-18000}, -#line 182 "zonetab.list" - {gperf_offsetof(stringpool, 92),34200}, -#line 103 "zonetab.list" - {gperf_offsetof(stringpool, 93),11*3600}, -#line 53 "zonetab.list" - {gperf_offsetof(stringpool, 94), -3*3600}, -#line 208 "zonetab.list" - {gperf_offsetof(stringpool, 95),36000}, -#line 49 "zonetab.list" - {gperf_offsetof(stringpool, 96),-2*3600}, -#line 120 "zonetab.list" - {gperf_offsetof(stringpool, 97), 34200}, - {-1}, {-1}, -#line 215 "zonetab.list" - {gperf_offsetof(stringpool, 100),25200}, -#line 242 "zonetab.list" - {gperf_offsetof(stringpool, 101),12600}, +#line 283 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74,39600}, #line 241 "zonetab.list" - {gperf_offsetof(stringpool, 102),28800}, -#line 240 "zonetab.list" - {gperf_offsetof(stringpool, 103),32400}, -#line 86 "zonetab.list" - {gperf_offsetof(stringpool, 104), 3*3600}, -#line 33 "zonetab.list" - {gperf_offsetof(stringpool, 105), -1*3600}, -#line 201 "zonetab.list" - {gperf_offsetof(stringpool, 106),21600}, -#line 148 "zonetab.list" - {gperf_offsetof(stringpool, 107), -25200}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75,21600}, #line 96 "zonetab.list" - {gperf_offsetof(stringpool, 108), 8*3600}, -#line 42 "zonetab.list" - {gperf_offsetof(stringpool, 109), -10*3600}, -#line 31 "zonetab.list" - {gperf_offsetof(stringpool, 110), 11*3600}, -#line 72 "zonetab.list" - {gperf_offsetof(stringpool, 111), 1*3600}, - {-1}, -#line 90 "zonetab.list" - {gperf_offsetof(stringpool, 113), 4*3600}, -#line 47 "zonetab.list" - {gperf_offsetof(stringpool, 114), 0*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, (5*3600+1800)}, +#line 197 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77,28800}, {-1}, +#line 258 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79,43200}, #line 78 "zonetab.list" - {gperf_offsetof(stringpool, 116), 1*3600}, -#line 77 "zonetab.list" - {gperf_offsetof(stringpool, 117), 1*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, 1*3600}, +#line 273 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81,18000}, +#line 86 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, 2*3600}, {-1}, -#line 95 "zonetab.list" - {gperf_offsetof(stringpool, 119), 7*3600}, -#line 313 "zonetab.list" - {gperf_offsetof(stringpool, 120),43200}, -#line 55 "zonetab.list" - {gperf_offsetof(stringpool, 121), -(3*3600+1800)}, -#line 184 "zonetab.list" - {gperf_offsetof(stringpool, 122),31500}, -#line 204 "zonetab.list" - {gperf_offsetof(stringpool, 123),45900}, #line 210 "zonetab.list" - {gperf_offsetof(stringpool, 124),-18000}, -#line 198 "zonetab.list" - {gperf_offsetof(stringpool, 125),14400}, -#line 57 "zonetab.list" - {gperf_offsetof(stringpool, 126), -4*3600}, -#line 197 "zonetab.list" - {gperf_offsetof(stringpool, 127),18000}, -#line 54 "zonetab.list" - {gperf_offsetof(stringpool, 128),-3*3600}, -#line 253 "zonetab.list" - {gperf_offsetof(stringpool, 129),-30600}, -#line 91 "zonetab.list" - {gperf_offsetof(stringpool, 130), 4*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84,36000}, +#line 281 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85,-7200}, + {-1}, {-1}, +#line 129 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, -21600}, +#line 188 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89,39600}, +#line 186 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90,-18000}, +#line 221 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91,-18000}, +#line 185 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92,34200}, +#line 106 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93,11*3600}, +#line 56 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, -3*3600}, +#line 211 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95,36000}, +#line 52 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96,-2*3600}, +#line 123 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, 34200}, + {-1}, {-1}, +#line 218 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str100,25200}, +#line 245 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101,12600}, +#line 244 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102,28800}, +#line 243 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103,32400}, +#line 89 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, 3*3600}, +#line 36 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, -1*3600}, +#line 204 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106,21600}, +#line 151 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, -25200}, #line 99 "zonetab.list" - {gperf_offsetof(stringpool, 131), 9*3600}, -#line 122 "zonetab.list" - {gperf_offsetof(stringpool, 132), 21600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, (6*3600+1800)}, +#line 45 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, -10*3600}, +#line 34 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str110, 11*3600}, +#line 75 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, 1*3600}, + {-1}, +#line 93 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str113, 4*3600}, +#line 50 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, 0*3600}, + {-1}, +#line 81 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str116, 1*3600}, +#line 80 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, 1*3600}, + {-1}, +#line 98 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str119, 2*3600}, +#line 316 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str120,43200}, +#line 58 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, -(2*3600+1800)}, #line 187 "zonetab.list" - {gperf_offsetof(stringpool, 133),16200}, -#line 132 "zonetab.list" - {gperf_offsetof(stringpool, 134), -10800}, -#line 121 "zonetab.list" - {gperf_offsetof(stringpool, 135), -21600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122,31500}, +#line 207 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str123,45900}, +#line 213 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124,-18000}, +#line 201 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str125,14400}, +#line 60 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, -4*3600}, +#line 200 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127,18000}, +#line 57 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128,-3*3600}, +#line 256 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129,-30600}, +#line 94 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, 4*3600}, +#line 102 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, 9*3600}, +#line 125 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, 21600}, +#line 190 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133,16200}, +#line 135 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, -10800}, +#line 124 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, -21600}, {-1}, -#line 236 "zonetab.list" - {gperf_offsetof(stringpool, 137),25200}, +#line 239 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137,25200}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 274 "zonetab.list" - {gperf_offsetof(stringpool, 143),36000}, -#line 266 "zonetab.list" - {gperf_offsetof(stringpool, 144),43200}, -#line 146 "zonetab.list" - {gperf_offsetof(stringpool, 145), -21600}, -#line 193 "zonetab.list" - {gperf_offsetof(stringpool, 146),32400}, -#line 220 "zonetab.list" - {gperf_offsetof(stringpool, 147),-3600}, -#line 214 "zonetab.list" - {gperf_offsetof(stringpool, 148),25200}, -#line 219 "zonetab.list" - {gperf_offsetof(stringpool, 149),0}, -#line 275 "zonetab.list" - {gperf_offsetof(stringpool, 150),46800}, -#line 109 "zonetab.list" - {gperf_offsetof(stringpool, 151), -32400}, +#line 277 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143,36000}, +#line 269 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144,43200}, +#line 149 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, -21600}, +#line 196 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str146,32400}, +#line 223 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147,-3600}, +#line 217 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str148,25200}, +#line 222 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149,0}, +#line 278 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str150,46800}, +#line 112 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, -32400}, {-1}, {-1}, -#line 68 "zonetab.list" - {gperf_offsetof(stringpool, 154), -11*3600}, +#line 71 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, -11*3600}, {-1}, {-1}, {-1}, -#line 321 "zonetab.list" - {gperf_offsetof(stringpool, 158),0}, +#line 324 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str158,0}, {-1}, -#line 178 "zonetab.list" - {gperf_offsetof(stringpool, 160), 18000}, #line 181 "zonetab.list" - {gperf_offsetof(stringpool, 161),37800}, -#line 265 "zonetab.list" - {gperf_offsetof(stringpool, 162),20700}, -#line 249 "zonetab.list" - {gperf_offsetof(stringpool, 163),37800}, -#line 108 "zonetab.list" - {gperf_offsetof(stringpool, 164), 16200}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str160, 18000}, +#line 184 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str161,37800}, +#line 268 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162,20700}, +#line 252 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str163,37800}, +#line 111 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, 16200}, {-1}, {-1}, +#line 33 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, 10*3600}, + {-1}, #line 30 "zonetab.list" - {gperf_offsetof(stringpool, 167), 10*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str169, 7*3600}, +#line 242 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170,16200}, +#line 209 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171,28800}, +#line 208 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str172,32400}, +#line 15 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str173, 0*3600}, +#line 232 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174,14400}, +#line 267 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str175,25200}, +#line 266 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176,25200}, +#line 226 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177,43200}, +#line 43 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str178, -8*3600}, +#line 225 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179,46800}, {-1}, -#line 27 "zonetab.list" - {gperf_offsetof(stringpool, 169), 7*3600}, -#line 239 "zonetab.list" - {gperf_offsetof(stringpool, 170),16200}, -#line 206 "zonetab.list" - {gperf_offsetof(stringpool, 171),28800}, -#line 205 "zonetab.list" - {gperf_offsetof(stringpool, 172),32400}, -#line 12 "zonetab.list" - {gperf_offsetof(stringpool, 173), 0*3600}, -#line 229 "zonetab.list" - {gperf_offsetof(stringpool, 174),14400}, -#line 264 "zonetab.list" - {gperf_offsetof(stringpool, 175),25200}, +#line 285 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str181,-10800}, #line 263 "zonetab.list" - {gperf_offsetof(stringpool, 176),25200}, -#line 223 "zonetab.list" - {gperf_offsetof(stringpool, 177),43200}, -#line 40 "zonetab.list" - {gperf_offsetof(stringpool, 178), -8*3600}, -#line 222 "zonetab.list" - {gperf_offsetof(stringpool, 179),46800}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182,39600}, +#line 103 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str183, 9*3600}, +#line 247 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str184,39600}, +#line 105 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, 10*3600}, +#line 146 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str186, 12600}, +#line 132 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str187, 10800}, +#line 101 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, 8*3600}, +#line 42 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, -7*3600}, +#line 133 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str190, 36000}, +#line 41 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, -6*3600}, +#line 206 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str192,49500}, +#line 301 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str193,18000}, +#line 212 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str194,-14400}, +#line 194 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str195,-43200}, {-1}, -#line 282 "zonetab.list" - {gperf_offsetof(stringpool, 181),-10800}, +#line 262 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197,28800}, +#line 182 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, 36000}, #line 260 "zonetab.list" - {gperf_offsetof(stringpool, 182),39600}, -#line 100 "zonetab.list" - {gperf_offsetof(stringpool, 183), 9*3600}, -#line 244 "zonetab.list" - {gperf_offsetof(stringpool, 184),39600}, -#line 102 "zonetab.list" - {gperf_offsetof(stringpool, 185), 10*3600}, -#line 143 "zonetab.list" - {gperf_offsetof(stringpool, 186), 12600}, -#line 129 "zonetab.list" - {gperf_offsetof(stringpool, 187), 10800}, -#line 98 "zonetab.list" - {gperf_offsetof(stringpool, 188), 8*3600}, -#line 39 "zonetab.list" - {gperf_offsetof(stringpool, 189), -7*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199,14400}, +#line 322 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str200,32400}, +#line 87 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str201, 2*3600}, +#line 289 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str202,39600}, +#line 155 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, 43200}, +#line 303 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str204,46800}, #line 130 "zonetab.list" - {gperf_offsetof(stringpool, 190), 36000}, -#line 38 "zonetab.list" - {gperf_offsetof(stringpool, 191), -6*3600}, -#line 203 "zonetab.list" - {gperf_offsetof(stringpool, 192),49500}, -#line 298 "zonetab.list" - {gperf_offsetof(stringpool, 193),18000}, -#line 209 "zonetab.list" - {gperf_offsetof(stringpool, 194),-14400}, -#line 191 "zonetab.list" - {gperf_offsetof(stringpool, 195),-43200}, - {-1}, -#line 259 "zonetab.list" - {gperf_offsetof(stringpool, 197),28800}, -#line 179 "zonetab.list" - {gperf_offsetof(stringpool, 198), 36000}, -#line 257 "zonetab.list" - {gperf_offsetof(stringpool, 199),14400}, -#line 319 "zonetab.list" - {gperf_offsetof(stringpool, 200),32400}, -#line 84 "zonetab.list" - {gperf_offsetof(stringpool, 201), 2*3600}, -#line 286 "zonetab.list" - {gperf_offsetof(stringpool, 202),39600}, -#line 152 "zonetab.list" - {gperf_offsetof(stringpool, 203), 43200}, -#line 300 "zonetab.list" - {gperf_offsetof(stringpool, 204),46800}, -#line 127 "zonetab.list" - {gperf_offsetof(stringpool, 205), 28800}, -#line 299 "zonetab.list" - {gperf_offsetof(stringpool, 206),50400}, -#line 85 "zonetab.list" - {gperf_offsetof(stringpool, 207), 2*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, 28800}, +#line 302 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206,50400}, +#line 88 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str207, -11*3600}, {-1}, -#line 142 "zonetab.list" - {gperf_offsetof(stringpool, 209), 19800}, +#line 145 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, 19800}, {-1}, -#line 314 "zonetab.list" - {gperf_offsetof(stringpool, 211),-10800}, -#line 288 "zonetab.list" - {gperf_offsetof(stringpool, 212),39600}, +#line 317 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str211,-10800}, +#line 291 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str212,39600}, {-1}, -#line 196 "zonetab.list" - {gperf_offsetof(stringpool, 214),-3600}, -#line 195 "zonetab.list" - {gperf_offsetof(stringpool, 215),0}, -#line 293 "zonetab.list" - {gperf_offsetof(stringpool, 216),-36000}, -#line 106 "zonetab.list" - {gperf_offsetof(stringpool, 217), 12*3600}, +#line 199 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str214,-3600}, +#line 198 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215,0}, +#line 296 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str216,-36000}, +#line 109 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, 12*3600}, +#line 131 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, -43200}, +#line 108 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str219,12*3600}, +#line 173 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, 32400}, #line 128 "zonetab.list" - {gperf_offsetof(stringpool, 218), -43200}, -#line 105 "zonetab.list" - {gperf_offsetof(stringpool, 219),12*3600}, -#line 170 "zonetab.list" - {gperf_offsetof(stringpool, 220), 32400}, -#line 125 "zonetab.list" - {gperf_offsetof(stringpool, 221), 39600}, - {-1}, -#line 283 "zonetab.list" - {gperf_offsetof(stringpool, 223),21600}, -#line 113 "zonetab.list" - {gperf_offsetof(stringpool, 224), -14400}, -#line 262 "zonetab.list" - {gperf_offsetof(stringpool, 225),39600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, 39600}, {-1}, -#line 11 "zonetab.list" - {gperf_offsetof(stringpool, 227), 0*3600}, -#line 301 "zonetab.list" - {gperf_offsetof(stringpool, 228),10800}, -#line 315 "zonetab.list" - {gperf_offsetof(stringpool, 229),43200}, -#line 291 "zonetab.list" - {gperf_offsetof(stringpool, 230),-10800}, -#line 20 "zonetab.list" - {gperf_offsetof(stringpool, 231), -7*3600}, -#line 248 "zonetab.list" - {gperf_offsetof(stringpool, 232),39600}, +#line 286 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str223,21600}, +#line 116 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, -14400}, +#line 265 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str225,39600}, {-1}, -#line 52 "zonetab.list" - {gperf_offsetof(stringpool, 234), -3*3600}, #line 14 "zonetab.list" - {gperf_offsetof(stringpool, 235), -4*3600}, - {-1}, {-1}, -#line 277 "zonetab.list" - {gperf_offsetof(stringpool, 238),18000}, -#line 188 "zonetab.list" - {gperf_offsetof(stringpool, 239),21600}, -#line 320 "zonetab.list" - {gperf_offsetof(stringpool, 240),28800}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str227, 0*3600}, +#line 304 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str228,10800}, +#line 318 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229,43200}, +#line 294 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str230,-10800}, +#line 23 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str231, -7*3600}, +#line 251 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232,39600}, {-1}, -#line 317 "zonetab.list" - {gperf_offsetof(stringpool, 242),-10800}, -#line 60 "zonetab.list" - {gperf_offsetof(stringpool, 243),-9*3600}, -#line 316 "zonetab.list" - {gperf_offsetof(stringpool, 244),-7200}, +#line 55 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str234, -3*3600}, +#line 17 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, -4*3600}, + {-1}, {-1}, +#line 280 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str238,18000}, +#line 191 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str239,21600}, +#line 323 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str240,28800}, {-1}, -#line 246 "zonetab.list" - {gperf_offsetof(stringpool, 246),25200}, -#line 245 "zonetab.list" - {gperf_offsetof(stringpool, 247),28800}, -#line 147 "zonetab.list" - {gperf_offsetof(stringpool, 248), -7200}, -#line 18 "zonetab.list" - {gperf_offsetof(stringpool, 249), -6*3600}, -#line 250 "zonetab.list" - {gperf_offsetof(stringpool, 250),50400}, -#line 165 "zonetab.list" - {gperf_offsetof(stringpool, 251), 28800}, -#line 16 "zonetab.list" - {gperf_offsetof(stringpool, 252), -5*3600}, -#line 76 "zonetab.list" - {gperf_offsetof(stringpool, 253), 1*3600}, +#line 320 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242,-7200}, +#line 63 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str243,-9*3600}, +#line 319 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str244,-3600}, {-1}, -#line 164 "zonetab.list" - {gperf_offsetof(stringpool, 255), 25200}, -#line 41 "zonetab.list" - {gperf_offsetof(stringpool, 256), -9*3600}, +#line 249 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str246,25200}, +#line 248 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str247,28800}, +#line 150 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str248, -7200}, +#line 21 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str249, -6*3600}, +#line 253 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str250,50400}, +#line 168 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str251, 28800}, +#line 19 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str252, -5*3600}, +#line 79 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str253, 1*3600}, {-1}, -#line 171 "zonetab.list" - {gperf_offsetof(stringpool, 258), 46800}, -#line 211 "zonetab.list" - {gperf_offsetof(stringpool, 259),-36000}, +#line 167 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str255, 25200}, +#line 44 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, -9*3600}, {-1}, -#line 308 "zonetab.list" - {gperf_offsetof(stringpool, 261),-14400}, -#line 119 "zonetab.list" - {gperf_offsetof(stringpool, 262), 14400}, -#line 123 "zonetab.list" - {gperf_offsetof(stringpool, 263), 3600}, -#line 28 "zonetab.list" - {gperf_offsetof(stringpool, 264), 8*3600}, -#line 124 "zonetab.list" - {gperf_offsetof(stringpool, 265), 3600}, -#line 153 "zonetab.list" - {gperf_offsetof(stringpool, 266), -12600}, -#line 110 "zonetab.list" - {gperf_offsetof(stringpool, 267), 10800}, -#line 289 "zonetab.list" - {gperf_offsetof(stringpool, 268),14400}, -#line 112 "zonetab.list" - {gperf_offsetof(stringpool, 269), 10800}, -#line 111 "zonetab.list" - {gperf_offsetof(stringpool, 270), 14400}, -#line 216 "zonetab.list" - {gperf_offsetof(stringpool, 271),36000}, +#line 174 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str258, 46800}, +#line 214 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str259,-36000}, {-1}, #line 311 "zonetab.list" - {gperf_offsetof(stringpool, 273),21600}, -#line 66 "zonetab.list" - {gperf_offsetof(stringpool, 274),-10*3600}, -#line 151 "zonetab.list" - {gperf_offsetof(stringpool, 275), 20700}, -#line 267 "zonetab.list" - {gperf_offsetof(stringpool, 276),-39600}, -#line 225 "zonetab.list" - {gperf_offsetof(stringpool, 277),-14400}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str261,-14400}, +#line 122 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str262, 14400}, +#line 126 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str263, 3600}, +#line 31 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str264, 8*3600}, +#line 127 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str265, 3600}, +#line 156 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str266, -12600}, +#line 113 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str267, 10800}, +#line 292 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str268,14400}, +#line 115 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str269, 10800}, +#line 114 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str270, 14400}, +#line 219 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str271,36000}, {-1}, -#line 224 "zonetab.list" - {gperf_offsetof(stringpool, 279),-10800}, -#line 67 "zonetab.list" - {gperf_offsetof(stringpool, 280),-10*3600}, -#line 237 "zonetab.list" - {gperf_offsetof(stringpool, 281),10800}, +#line 314 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str273,21600}, +#line 69 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str274,-10*3600}, +#line 154 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str275, 20700}, +#line 270 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str276,-39600}, +#line 228 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str277,-14400}, + {-1}, +#line 227 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str279,-10800}, +#line 70 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str280,-10*3600}, +#line 240 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str281,10800}, {-1}, {-1}, -#line 297 "zonetab.list" - {gperf_offsetof(stringpool, 284),32400}, -#line 175 "zonetab.list" - {gperf_offsetof(stringpool, 285), 28800}, -#line 134 "zonetab.list" - {gperf_offsetof(stringpool, 286), 7200}, -#line 149 "zonetab.list" - {gperf_offsetof(stringpool, 287), 23400}, -#line 107 "zonetab.list" - {gperf_offsetof(stringpool, 288),13*3600}, -#line 230 "zonetab.list" - {gperf_offsetof(stringpool, 289),-10800}, -#line 307 "zonetab.list" - {gperf_offsetof(stringpool, 290),18000}, +#line 300 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str284,32400}, +#line 178 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str285, 28800}, +#line 137 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str286, 7200}, +#line 152 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str287, 23400}, +#line 110 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str288,13*3600}, +#line 233 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str289,-10800}, +#line 310 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str290,18000}, {-1}, {-1}, -#line 155 "zonetab.list" - {gperf_offsetof(stringpool, 293), 25200}, -#line 258 "zonetab.list" - {gperf_offsetof(stringpool, 294),18000}, -#line 227 "zonetab.list" - {gperf_offsetof(stringpool, 295),-21600}, +#line 158 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str293, 25200}, #line 261 "zonetab.list" - {gperf_offsetof(stringpool, 296),43200}, -#line 213 "zonetab.list" - {gperf_offsetof(stringpool, 297),-3600}, -#line 154 "zonetab.list" - {gperf_offsetof(stringpool, 298), 28800}, - {-1}, -#line 243 "zonetab.list" - {gperf_offsetof(stringpool, 300),21600}, -#line 114 "zonetab.list" - {gperf_offsetof(stringpool, 301), 34200}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str294,18000}, +#line 230 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str295,-21600}, +#line 264 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str296,43200}, +#line 216 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str297,-3600}, #line 157 "zonetab.list" - {gperf_offsetof(stringpool, 302), -28800}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str298, 28800}, {-1}, +#line 246 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str300,21600}, #line 117 "zonetab.list" - {gperf_offsetof(stringpool, 304), -21600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str301, 34200}, +#line 160 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str302, -28800}, {-1}, -#line 156 "zonetab.list" - {gperf_offsetof(stringpool, 306), -14400}, -#line 116 "zonetab.list" - {gperf_offsetof(stringpool, 307), -3600}, -#line 228 "zonetab.list" - {gperf_offsetof(stringpool, 308),-32400}, -#line 294 "zonetab.list" - {gperf_offsetof(stringpool, 309),18000}, -#line 37 "zonetab.list" - {gperf_offsetof(stringpool, 310), -5*3600}, -#line 137 "zonetab.list" - {gperf_offsetof(stringpool, 311), 7200}, -#line 58 "zonetab.list" - {gperf_offsetof(stringpool, 312),-8*3600}, -#line 304 "zonetab.list" - {gperf_offsetof(stringpool, 313),28800}, -#line 303 "zonetab.list" - {gperf_offsetof(stringpool, 314),32400}, -#line 284 "zonetab.list" - {gperf_offsetof(stringpool, 315),14400}, +#line 120 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str304, -21600}, {-1}, -#line 295 "zonetab.list" - {gperf_offsetof(stringpool, 317),18000}, +#line 159 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str306, -14400}, +#line 119 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str307, -3600}, +#line 231 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str308,-32400}, +#line 297 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str309,18000}, +#line 40 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str310, -5*3600}, +#line 140 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str311, 7200}, +#line 61 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str312,-8*3600}, +#line 307 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str313,28800}, +#line 306 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str314,32400}, +#line 287 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str315,14400}, {-1}, -#line 166 "zonetab.list" - {gperf_offsetof(stringpool, 319), 7200}, +#line 298 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str317,18000}, + {-1}, +#line 169 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str319, 7200}, {-1}, {-1}, {-1}, {-1}, -#line 97 "zonetab.list" - {gperf_offsetof(stringpool, 324), 8*3600}, +#line 100 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str324, 8*3600}, {-1}, -#line 50 "zonetab.list" - {gperf_offsetof(stringpool, 326), -(2*3600+1800)}, -#line 285 "zonetab.list" - {gperf_offsetof(stringpool, 327),-10800}, +#line 53 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str326, -(1*3600+1800)}, +#line 288 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str327,-10800}, {-1}, {-1}, -#line 287 "zonetab.list" - {gperf_offsetof(stringpool, 330),14400}, +#line 290 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str330,14400}, {-1}, -#line 169 "zonetab.list" - {gperf_offsetof(stringpool, 332), 36000}, +#line 172 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str332, 36000}, {-1}, -#line 235 "zonetab.list" - {gperf_offsetof(stringpool, 334),25200}, -#line 234 "zonetab.list" - {gperf_offsetof(stringpool, 335),28800}, +#line 238 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str334,25200}, +#line 237 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str335,28800}, {-1}, {-1}, -#line 232 "zonetab.list" - {gperf_offsetof(stringpool, 338),-14400}, +#line 235 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str338,-14400}, {-1}, {-1}, {-1}, -#line 44 "zonetab.list" - {gperf_offsetof(stringpool, 342), -12*3600}, -#line 61 "zonetab.list" - {gperf_offsetof(stringpool, 343),-9*3600}, -#line 162 "zonetab.list" - {gperf_offsetof(stringpool, 344), -14400}, -#line 141 "zonetab.list" - {gperf_offsetof(stringpool, 345), -36000}, +#line 47 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str342, -12*3600}, +#line 64 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str343,-9*3600}, +#line 165 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str344, -14400}, +#line 144 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str345, -36000}, {-1}, -#line 306 "zonetab.list" - {gperf_offsetof(stringpool, 347),-10800}, +#line 309 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str347,-10800}, {-1}, -#line 305 "zonetab.list" - {gperf_offsetof(stringpool, 349),-7200}, +#line 308 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str349,-7200}, +#line 329 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str350,18000}, +#line 328 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str351,21600}, +#line 250 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str352,14400}, #line 326 "zonetab.list" - {gperf_offsetof(stringpool, 350),18000}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str353,32400}, #line 325 "zonetab.list" - {gperf_offsetof(stringpool, 351),21600}, -#line 247 "zonetab.list" - {gperf_offsetof(stringpool, 352),14400}, -#line 323 "zonetab.list" - {gperf_offsetof(stringpool, 353),32400}, -#line 322 "zonetab.list" - {gperf_offsetof(stringpool, 354),36000}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str354,36000}, {-1}, {-1}, {-1}, -#line 63 "zonetab.list" - {gperf_offsetof(stringpool, 358), -9*3600}, -#line 144 "zonetab.list" - {gperf_offsetof(stringpool, 359), 7200}, +#line 66 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str358, -9*3600}, +#line 147 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str359, 7200}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 167 "zonetab.list" - {gperf_offsetof(stringpool, 365), 21600}, +#line 170 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str365, 21600}, {-1}, -#line 180 "zonetab.list" - {gperf_offsetof(stringpool, 367), 32400}, +#line 183 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str367, 32400}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 318 "zonetab.list" - {gperf_offsetof(stringpool, 375),25200}, +#line 321 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str375,25200}, {-1}, -#line 115 "zonetab.list" - {gperf_offsetof(stringpool, 377), 36000}, -#line 231 "zonetab.list" - {gperf_offsetof(stringpool, 378),43200}, +#line 118 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str377, 36000}, +#line 234 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str378,43200}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 173 "zonetab.list" - {gperf_offsetof(stringpool, 387), -25200}, +#line 176 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str387, -25200}, {-1}, {-1}, {-1}, -#line 310 "zonetab.list" - {gperf_offsetof(stringpool, 391),36000}, -#line 309 "zonetab.list" - {gperf_offsetof(stringpool, 392),39600}, +#line 313 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str391,36000}, +#line 312 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str392,39600}, {-1}, {-1}, -#line 140 "zonetab.list" - {gperf_offsetof(stringpool, 395), 7200}, +#line 143 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str395, 7200}, {-1}, {-1}, -#line 168 "zonetab.list" - {gperf_offsetof(stringpool, 398), 28800}, -#line 290 "zonetab.list" - {gperf_offsetof(stringpool, 399),39600}, +#line 171 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str398, 28800}, +#line 293 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str399,39600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 118 "zonetab.list" - {gperf_offsetof(stringpool, 408), -3600}, +#line 121 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str408, -3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 296 "zonetab.list" - {gperf_offsetof(stringpool, 417),46800}, -#line 163 "zonetab.list" - {gperf_offsetof(stringpool, 418), -39600}, +#line 299 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str417,46800}, +#line 166 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str418, -39600}, {-1}, {-1}, -#line 161 "zonetab.list" - {gperf_offsetof(stringpool, 421), -18000}, +#line 164 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str421, -18000}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 312 "zonetab.list" - {gperf_offsetof(stringpool, 427),39600}, -#line 69 "zonetab.list" - {gperf_offsetof(stringpool, 428),-12*3600}, +#line 315 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str427,39600}, +#line 72 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str428,-12*3600}, {-1}, {-1}, {-1}, -#line 136 "zonetab.list" - {gperf_offsetof(stringpool, 432), 43200}, +#line 139 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str432, 43200}, {-1}, {-1}, -#line 46 "zonetab.list" - {gperf_offsetof(stringpool, 435), 0*3600}, +#line 49 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str435, 0*3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 145 "zonetab.list" - {gperf_offsetof(stringpool, 443), 32400}, +#line 148 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str443, 32400}, {-1}, -#line 131 "zonetab.list" - {gperf_offsetof(stringpool, 445), 7200}, +#line 134 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str445, 7200}, {-1}, {-1}, {-1}, -#line 292 "zonetab.list" - {gperf_offsetof(stringpool, 449),10800}, +#line 295 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str449,10800}, {-1}, {-1}, -#line 150 "zonetab.list" - {gperf_offsetof(stringpool, 452), 21600}, +#line 153 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str452, 21600}, {-1}, {-1}, -#line 302 "zonetab.list" - {gperf_offsetof(stringpool, 455),43200}, +#line 305 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str455,43200}, {-1}, {-1}, -#line 176 "zonetab.list" - {gperf_offsetof(stringpool, 458), 3600}, +#line 179 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str458, 3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 135 "zonetab.list" - {gperf_offsetof(stringpool, 466), 18000}, +#line 138 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str466, 18000}, {-1}, -#line 174 "zonetab.list" - {gperf_offsetof(stringpool, 468), 36000}, +#line 177 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str468, 36000}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 324 "zonetab.list" - {gperf_offsetof(stringpool, 476),36000}, -#line 172 "zonetab.list" - {gperf_offsetof(stringpool, 477), -18000}, +#line 327 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str476,36000}, +#line 175 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str477, -18000}, {-1}, {-1}, {-1}, {-1}, -#line 160 "zonetab.list" - {gperf_offsetof(stringpool, 482), -10800}, +#line 163 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str482, -10800}, {-1}, {-1}, -#line 62 "zonetab.list" - {gperf_offsetof(stringpool, 485), -9*3600}, -#line 159 "zonetab.list" - {gperf_offsetof(stringpool, 486), 10800}, +#line 65 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str485, -9*3600}, +#line 162 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str486, 10800}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 233 "zonetab.list" - {gperf_offsetof(stringpool, 492),28800}, +#line 236 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str492,28800}, {-1}, {-1}, {-1}, {-1}, -#line 158 "zonetab.list" - {gperf_offsetof(stringpool, 497), 3600}, +#line 161 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str497, 3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 177 "zonetab.list" - {gperf_offsetof(stringpool, 540), 3600}, +#line 180 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str540, 3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 59 "zonetab.list" - {gperf_offsetof(stringpool, 563), -8*3600}, +#line 62 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str563, -8*3600}, {-1}, {-1}, -#line 104 "zonetab.list" - {gperf_offsetof(stringpool, 566),12*3600}, -#line 139 "zonetab.list" - {gperf_offsetof(stringpool, 567), 0}, +#line 107 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str566,12*3600}, +#line 142 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str567, 0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 138 "zonetab.list" - {gperf_offsetof(stringpool, 619), -10800} +#line 141 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str619, -10800} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) @@ -1558,5 +1560,5 @@ zonetab (register const char *str, register size_t len) } return 0; } -#line 327 "zonetab.list" +#line 330 "zonetab.list" diff --git a/ext/date/zonetab.list b/ext/date/zonetab.list index d2f902d2d5..63b6873447 100644 --- a/ext/date/zonetab.list +++ b/ext/date/zonetab.list @@ -1,9 +1,12 @@ %{ +#define GPERF_DOWNCASE 1 +#define GPERF_CASE_STRNCMP 1 +#define gperf_case_strncmp strncasecmp struct zone { int name; int offset; }; -static const struct zone *zonetab(); +static const struct zone *zonetab(register const char *str, register size_t len); %} struct zone; @@ -313,8 +316,8 @@ vut,39600 wakt,43200 warst,-10800 wft,43200 -wgst,-7200 -wgt,-10800 +wgst,-3600 +wgt,-7200 wib,25200 wit,32400 wita,28800 |
