5
5

More than 5 years have passed since last update.

「Date.new > 0」はなぜfalseなのか

Last updated at Posted at 2015-02-21

こちらの記事を見て気になったので調べました。

Ruby で Date.new > 0 は true か?それとも false か? - Qiita

マニュアル読んでみる

> < の挙動は <=> で決まるので、Date#<=>のマニュアルを読んでみます。

instance method Date#<=>

self <=> other -> Integer
ふたつを比較し、-1、零、あるいは 1 を返します。
other は日付オブジェクトか、 天文学的なユリウス日をあらわす数値でなければなりません。

class Date

ユリウス日

ユリウス日は紀元前4713年1月1日 (ユリウス暦) 正午 (グリニッジ平均時) を 暦元とした通日 (経過日数) です。

この文書で、天文学的なユリウス日とは、本来のユリウス日と同じものです。 また、年代学的なユリウス日とは、地方時における零時を一日の始まりとする 流儀です。

この文書で、単に「ユリウス日」といった場合、それは本来のユリウス日でな く、「年代学的なユリウス日」を意味しています。

なるほど分からん。

ソース眺めてみる

ソースを眺めてみたら、引数が数値ならDate#ajdと比較してるっぽかった。

ruby/date_core.c#L6262-L6282

otherがDateクラスでないならcmp_gen呼んでるっぽい。

d_lite_cmp
/*
 * call-seq:
 *    d <=> other  -> -1, 0, +1 or nil
 *
 * 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.
 *
 *    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
 *
 * See also Comparable.
 */
static VALUE
d_lite_cmp(VALUE self, VALUE other)
{
    if (!k_date_p(other))
    return cmp_gen(self, other);

...

ruby/date_core.c#L6193-L6199

cmp_genではotherがNumericクラスなら自身のajdメソッドを呼んでotherと比較してるっぽい。

cmp_gen
static VALUE
cmp_gen(VALUE self, VALUE other)
{
    get_d1(self);

    if (k_numeric_p(other))
    return f_cmp(m_ajd(dat), other);
...

ほんとに適当ですが。

Date#ajd, Date#jd

またマニュアルを見てみる。
instance method Date#ajd

このメソッドは Date#jd と似ていますが、天文学的なユリウス日を返します。 時刻を含みます。

instance method Date#jd

ユリウス日を返します。 時刻を含みません。
Date#ajd も参照してください。

Date.new.ajdを見てみたらRationalで(-1/2)でした。
これと比較してるのでDate.new > 0 #=> falseなのでした。

require 'date'

Date.new.ajd #=> (-1/2)

Date.new == Date.new.ajd #=> true

Date.new == -1/2r #=> true
Date.new == -0.5 #=> true
Date.new > 0 #=> false

初期値がなぜ(-1/2)なのか?
さぁ。

(追記: コメントにて理由を教えていただけました!)

ちなみに今日のajdは(4914149/2)でした。

today = Date.today
=> #<Date: 2015-02-21 ((2457075j,0s,0n),+0s,2299161j)>

today.ajd #=> (4914149/2)

today.jd #=> 2457075
today.ajd.to_f #=> 2457074.5

[*Date.new(-4712)..Date.today].size #=> 2457076

時刻も含むってかいてあるけどこれ12時間刻みの時刻しか取得できないんじゃ?意味あるの?
よく分かりませんがとりあえずもうタイトルの謎は分かったからおわり。

(追記: これも、たぶんコメントでいただいたことと同じ理由だと思います。)

参考

ユリウス通日 - Wikipedia

5
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5