DateTime 類別
DateTime
¶ ↑
Date
的子類別,可輕鬆處理日期、小時、分鐘、秒數和偏移量。
DateTime
類別已標示為已棄用。請使用 Time
類別。
DateTime
沒有考慮任何閏秒,也不會追蹤任何夏令時間規則。
使用 DateTime::new
、DateTime::jd
、DateTime::ordinal
、DateTime::commercial
、DateTime::parse
、DateTime::strptime
、DateTime::now
、Time#to_datetime
等建立 DateTime
物件。
require 'date' DateTime.new(2001,2,3,4,5,6) #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
天、小時、分鐘或秒數的最後一個元素可以是分數。分數的精度假設最多為奈秒。
DateTime.new(2001,2,3.5) #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
一個選用參數,偏移量,表示當地時間和 UTC 之間的差異。例如,Rational(3,24)
代表領先 UTC 3 小時,Rational(-5,24)
代表落後 UTC 5 小時。偏移量應為 -1 到 +1,其精度假設最多為秒。預設值為零(等於 UTC)。
DateTime.new(2001,2,3,4,5,6,Rational(3,24)) #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
偏移量也接受字串形式
DateTime.new(2001,2,3,4,5,6,'+03:00') #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
一個選用參數,曆法改革日(start
),表示儒略日數字,應為 2298874 到 2426355 或負/正無限大。預設值為 Date::ITALY
(2299161=1582-10-15)。
DateTime
物件有各種方法。請參閱每個參考。
d = DateTime.parse('3rd Feb 2001 04:05:06+03:30') #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...> d.hour #=> 4 d.min #=> 5 d.sec #=> 6 d.offset #=> (7/48) d.zone #=> "+03:30" d += Rational('1.5') #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...> d = d.new_offset('+09:00') #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...> d.strftime('%I:%M:%S %p') #=> "09:35:06 PM" d > DateTime.new(1999) #=> true
您應該在什麼時候使用 DateTime
,在什麼時候使用 Time
?¶ ↑
普遍的誤解是威廉·莎士比亞和米格爾·德·塞萬提斯在歷史上的同一天去世,因此聯合國教科文組織將4月23日定為世界圖書和版權日。然而,由於英格蘭尚未採用格里曆改革(直到1752年才採用),他們的死亡時間實際上相差10天。由於Ruby的Time
類別實作了前攝格里曆,而且沒有曆法改革的概念,因此無法用Time
物件來表達這一點。這時DateTime
就派上用場了
shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND) #=> Tue, 23 Apr 1616 00:00:00 +0000 cervantes = DateTime.iso8601('1616-04-23', Date::ITALY) #=> Sat, 23 Apr 1616 00:00:00 +0000
你已經可以看到有些地方很奇怪,星期幾不同。進一步探討
cervantes == shakespeare #=> false (shakespeare - cervantes).to_i #=> 10
這表明他們實際上相差10天(實際上相差11天,因為塞萬提斯早一天去世,但於23日下葬)。我們可以使用gregorian
方法將莎士比亞的死亡日期轉換為格里曆,以查看實際日期
shakespeare.gregorian #=> Tue, 03 May 1616 00:00:00 +0000
因此,有人認為,由於英格蘭現在使用格里曆,因此4月23日在埃文河畔斯特拉特福舉行的所有慶祝活動實際上都是錯誤的日期。當我們跨越改革日期界線時,你就可以明白原因
# start off with the anniversary of Shakespeare's birth in 1751 shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND) #=> Tue, 23 Apr 1751 00:00:00 +0000 # add 366 days since 1752 is a leap year and April 23 is after February 29 shakespeare + 366 #=> Thu, 23 Apr 1752 00:00:00 +0000 # add another 365 days to take us to the anniversary in 1753 shakespeare + 366 + 365 #=> Fri, 04 May 1753 00:00:00 +0000
如你所見,如果我們準確追蹤莎士比亞生日以來的太陽年數,那麼正確的紀念日應該是5月4日,而不是4月23日。
因此,什麼時候應該在 Ruby 中使用 DateTime
,什麼時候應該使用 Time
?由於你的應用程式可能處理的是目前的日期和時間,因此你幾乎一定會想要使用 Time
。然而,如果你需要在歷史脈絡中處理日期和時間,你會想要使用 DateTime
,以避免犯下與聯合國教科文組織相同的錯誤。如果你還必須處理時區,那麼祝你好運 - 只需記住你可能正在處理 當地太陽時間,因為直到 19 世紀,鐵路的引入才需要 標準時間,最終是時區。
公用類別方法
使用指定的範本解析日期和時間的指定表示形式,並傳回已解析元素的雜湊。與 strftime 不同,_strptime 不支援指定旗標和寬度。
另請參閱 strptime(3) 和 strftime
。
static VALUE datetime_s__strptime(int argc, VALUE *argv, VALUE klass) { return date_s__strptime_internal(argc, argv, klass, "%FT%T%z"); }
與 DateTime.new
相同。
static VALUE datetime_s_civil(int argc, VALUE *argv, VALUE klass) { return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass)); }
建立表示指定週日期的 DateTime
物件。
DateTime.commercial(2001) #=> #<DateTime: 2001-01-01T00:00:00+00:00 ...> DateTime.commercial(2002) #=> #<DateTime: 2001-12-31T00:00:00+00:00 ...> DateTime.commercial(2001,5,6,4,5,6,'+7') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
static VALUE datetime_s_commercial(int argc, VALUE *argv, VALUE klass) { VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; int w, d, h, min, s, rof; double sg; rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg); y = INT2FIX(-4712); w = 1; d = 1; h = min = s = 0; fr2 = INT2FIX(0); rof = 0; sg = DEFAULT_SG; switch (argc) { case 8: val2sg(vsg, sg); case 7: val2off(vof, rof); case 6: check_numeric(vs, "second"); num2int_with_frac(s, positive_inf); case 5: check_numeric(vmin, "minute"); num2int_with_frac(min, 5); case 4: check_numeric(vh, "hour"); num2int_with_frac(h, 4); case 3: check_numeric(vd, "cwday"); num2int_with_frac(d, 3); case 2: check_numeric(vw, "cweek"); w = NUM2INT(vw); case 1: check_numeric(vy, "year"); y = vy; } { VALUE nth; int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns; if (!valid_commercial_p(y, w, d, sg, &nth, &ry, &rw, &rd, &rjd, &ns)) rb_raise(eDateError, "invalid date"); if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(eDateError, "invalid date"); canon24oc(); rjd2 = jd_local_to_utc(rjd, time_to_df(rh, rmin, rs), rof); ret = d_complex_new_internal(klass, nth, rjd2, 0, INT2FIX(0), rof, sg, 0, 0, 0, rh, rmin, rs, HAVE_JD | HAVE_TIME); } add_frac(); return ret; }
根據一些 RFC 2616 格式,從字串中解析來建立新的 DateTime
物件。
DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT') #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
根據一些典型的 ISO 8601 格式,從字串中解析來建立新的 DateTime
物件。
DateTime.iso8601('2001-02-03T04:05:06+07:00') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.iso8601('20010203T040506+0700') #=> #<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 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
建立表示指定曆法儒略日數的 DateTime
物件。
DateTime.jd(2451944) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> DateTime.jd(2451945) #=> #<DateTime: 2001-02-04T00:00:00+00:00 ...> DateTime.jd(Rational('0.5')) #=> #<DateTime: -4712-01-01T12:00:00+00:00 ...>
static VALUE datetime_s_jd(int argc, VALUE *argv, VALUE klass) { VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret; int h, min, s, rof; double sg; rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg); jd = INT2FIX(0); h = min = s = 0; fr2 = INT2FIX(0); rof = 0; sg = DEFAULT_SG; switch (argc) { case 6: val2sg(vsg, sg); case 5: val2off(vof, rof); case 4: check_numeric(vs, "second"); num2int_with_frac(s, positive_inf); case 3: check_numeric(vmin, "minute"); num2int_with_frac(min, 3); case 2: check_numeric(vh, "hour"); num2int_with_frac(h, 2); case 1: check_numeric(vjd, "jd"); num2num_with_frac(jd, 1); } { VALUE nth; int rh, rmin, rs, rjd, rjd2; if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(eDateError, "invalid date"); canon24oc(); decode_jd(jd, &nth, &rjd); rjd2 = jd_local_to_utc(rjd, time_to_df(rh, rmin, rs), rof); ret = d_complex_new_internal(klass, nth, rjd2, 0, INT2FIX(0), rof, sg, 0, 0, 0, rh, rmin, rs, HAVE_JD | HAVE_TIME); } add_frac(); return ret; }
根據一些典型的 JIS X 0301 格式,透過從字串剖析來建立新的 DateTime
物件。
DateTime.jisx0301('H13.02.03T04:05:06+07:00') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
對於沒有年代的年份,舊格式,假設為平成。
DateTime.jisx0301('13.02.03T04:05:06+07:00') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
請參閱 as_json
。
# File ext/json/lib/json/add/date_time.rb, line 10 def self.json_create(object) args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') of_a, of_b = object['of'].split('/') if of_b and of_b != '0' args << Rational(of_a.to_i, of_b.to_i) else args << of_a end args << object['sg'] civil(*args) end
與 DateTime.new
相同。
static VALUE datetime_s_civil(int argc, VALUE *argv, VALUE klass) { return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass)); }
建立表示目前時間的 DateTime
物件。
DateTime.now #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...>
static VALUE datetime_s_now(int argc, VALUE *argv, VALUE klass) { VALUE vsg, nth, ret; double sg; #ifdef HAVE_CLOCK_GETTIME struct timespec ts; #else struct timeval tv; #endif time_t sec; struct tm tm; long sf, of; int y, ry, m, d, h, min, s; rb_scan_args(argc, argv, "01", &vsg); if (argc < 1) sg = DEFAULT_SG; else sg = NUM2DBL(vsg); #ifdef HAVE_CLOCK_GETTIME if (clock_gettime(CLOCK_REALTIME, &ts) == -1) rb_sys_fail("clock_gettime"); sec = ts.tv_sec; #else if (gettimeofday(&tv, NULL) == -1) rb_sys_fail("gettimeofday"); sec = tv.tv_sec; #endif tzset(); if (!localtime_r(&sec, &tm)) rb_sys_fail("localtime"); y = tm.tm_year + 1900; m = tm.tm_mon + 1; d = tm.tm_mday; h = tm.tm_hour; min = tm.tm_min; s = tm.tm_sec; if (s == 60) s = 59; #ifdef HAVE_STRUCT_TM_TM_GMTOFF of = tm.tm_gmtoff; #elif defined(HAVE_TIMEZONE) #if defined(HAVE_ALTZONE) && !defined(_AIX) of = (long)-((tm.tm_isdst > 0) ? altzone : timezone); #else of = (long)-timezone; if (tm.tm_isdst) { time_t sec2; tm.tm_isdst = 0; sec2 = mktime(&tm); of += (long)difftime(sec2, sec); } #endif #elif defined(HAVE_TIMEGM) { time_t sec2; sec2 = timegm(&tm); of = (long)difftime(sec2, sec); } #else { struct tm tm2; time_t sec2; if (!gmtime_r(&sec, &tm2)) rb_sys_fail("gmtime"); tm2.tm_isdst = tm.tm_isdst; sec2 = mktime(&tm2); of = (long)difftime(sec, sec2); } #endif #ifdef HAVE_CLOCK_GETTIME sf = ts.tv_nsec; #else sf = tv.tv_usec * 1000; #endif if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) { of = 0; rb_warning("invalid offset is ignored"); } decode_year(INT2FIX(y), -1, &nth, &ry); ret = d_complex_new_internal(klass, nth, 0, 0, LONG2NUM(sf), (int)of, GREGORIAN, ry, m, d, h, min, s, HAVE_CIVIL | HAVE_TIME); { get_d1(ret); set_sg(dat, sg); } return ret; }
建立表示給定序數日期的 DateTime
物件。
DateTime.ordinal(2001,34) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...> DateTime.ordinal(2001,34,4,5,6,'+7') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.ordinal(2001,-332,-20,-55,-54,'+7') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
static VALUE datetime_s_ordinal(int argc, VALUE *argv, VALUE klass) { VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret; int d, h, min, s, rof; double sg; rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg); y = INT2FIX(-4712); d = 1; h = min = s = 0; fr2 = INT2FIX(0); rof = 0; sg = DEFAULT_SG; switch (argc) { case 7: val2sg(vsg, sg); case 6: val2off(vof, rof); case 5: check_numeric(vs, "second"); num2int_with_frac(s, positive_inf); case 4: check_numeric(vmin, "minute"); num2int_with_frac(min, 4); case 3: check_numeric(vh, "hour"); num2int_with_frac(h, 3); case 2: check_numeric(vd, "yday"); num2int_with_frac(d, 2); case 1: check_numeric(vy, "year"); y = vy; } { VALUE nth; int ry, rd, rh, rmin, rs, rjd, rjd2, ns; if (!valid_ordinal_p(y, d, sg, &nth, &ry, &rd, &rjd, &ns)) rb_raise(eDateError, "invalid date"); if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs)) rb_raise(eDateError, "invalid date"); canon24oc(); rjd2 = jd_local_to_utc(rjd, time_to_df(rh, rmin, rs), rof); ret = d_complex_new_internal(klass, nth, rjd2, 0, INT2FIX(0), rof, sg, 0, 0, 0, rh, rmin, rs, HAVE_JD | HAVE_TIME); } add_frac(); return ret; }
剖析日期和時間的給定表示形式,並建立 DateTime
物件。
此方法不會作為驗證器運作。如果輸入字串不完全符合有效格式,您可能會得到難以理解的結果。應該考慮使用 DateTime.strptime
代替此方法。
如果選擇性的第二個引數為 true,且偵測到的年份在「00」到「99」的範圍內,則使其完整。
DateTime.parse('2001-02-03T04:05:06+07:00') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.parse('20010203T040506+0700') #=> #<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 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_parse(int argc, VALUE *argv, VALUE klass) { VALUE str, comp, sg, opt; rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: comp = Qtrue; case 2: sg = INT2FIX(DEFAULT_SG); } { 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); } }
根據一些典型的 RFC 2822 格式,透過從字串剖析來建立新的 DateTime
物件。
DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
根據一些典型的 RFC 3339 格式,透過從字串剖析來建立新的 DateTime
物件。
DateTime.rfc3339('2001-02-03T04:05:06+07:00') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
根據一些典型的 RFC 2822 格式,透過從字串剖析來建立新的 DateTime
物件。
DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
使用給定的範本剖析日期和時間的給定表示形式,並建立 DateTime
物件。與 strftime 不同,strptime 不支援旗標和寬度規格。
DateTime.strptime('2001-02-03T04:05:06+07:00', '%Y-%m-%dT%H:%M:%S%z') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.strptime('03-02-2001 04:05:06 PM', '%d-%m-%Y %I:%M:%S %p') #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...> DateTime.strptime('2001-W05-6T04:05:06+07:00', '%G-W%V-%uT%H:%M:%S%z') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.strptime('2001 04 6 04 05 06 +7', '%Y %U %w %H %M %S %z') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.strptime('2001 05 6 04 05 06 +7', '%Y %W %u %H %M %S %z') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...> DateTime.strptime('-1', '%s') #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...> DateTime.strptime('-1000', '%Q') #=> #<DateTime: 1969-12-31T23:59:59+00:00 ...> DateTime.strptime('sat3feb014pm+7', '%a%d%b%y%H%p%z') #=> #<DateTime: 2001-02-03T16:00:00+07:00 ...>
另請參閱 strptime(3) 和 strftime
。
static VALUE datetime_s_strptime(int argc, VALUE *argv, VALUE klass) { VALUE str, fmt, sg; rb_scan_args(argc, argv, "03", &str, &fmt, &sg); switch (argc) { case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: fmt = rb_str_new2("%FT%T%z"); case 2: sg = INT2FIX(DEFAULT_SG); } { VALUE argv2[2], hash; argv2[0] = str; argv2[1] = fmt; hash = date_s__strptime(2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } }
根據一些典型的 XML Schema 格式,透過從字串剖析來建立新的 DateTime
物件。
DateTime.xmlschema('2001-02-03T04:05:06+07:00') #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
當字串長度大於 limit 時,會引發 ArgumentError
。你可以透過傳遞 limit: nil
來停止此檢查,但請注意解析可能需要很長的時間。
static VALUE datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; rb_scan_args(argc, argv, "02:", &str, &sg, &opt); if (!NIL_P(opt)) argc--; switch (argc) { case 0: str = rb_str_new2("-4712-01-01T00:00:00+00:00"); case 1: sg = INT2FIX(DEFAULT_SG); } { 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); } }
公開執行個體方法
方法 DateTime#as_json
和 DateTime.json_create
可用於序列化和反序列化 DateTime 物件;請參閱 Marshal
。
方法 DateTime#as_json
會序列化 self
,傳回一個代表 self
的 2 元素雜湊。
require 'json/add/datetime' x = DateTime.now.as_json # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
方法 JSON.create
會反序列化此類雜湊,傳回一個 DateTime 物件。
DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"
# File ext/json/lib/json/add/date_time.rb, line 39 def as_json(*) { JSON.create_id => self.class.name, 'y' => year, 'm' => month, 'd' => day, 'H' => hour, 'M' => min, 'S' => sec, 'of' => offset.to_s, 'sg' => start, } end
傳回名稱/值配對的雜湊,用於樣式比對。可能的鍵為::year
、:month
、:day
、:wday
、:yday
、:hour
、:min
、:sec
、:sec_fraction
、:zone
。
可能的用法
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"
請注意,也可以將樣式解構與類別檢查結合使用。
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); }
傳回範圍 (0..23) 內的小時。
DateTime.new(2001, 2, 3, 4, 5, 6).hour # => 4
static VALUE d_lite_hour(VALUE self) { get_d1(self); return INT2FIX(m_hour(dat)); }
此方法等於 strftime(‘%FT%T%:z’)。選用參數 n
是小數秒的位數。
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9) #=> "2001-02-03T04:05:06.123456789+07:00"
static VALUE dt_lite_iso8601(int argc, VALUE *argv, VALUE self) { long n = 0; rb_check_arity(argc, 0, 1); if (argc >= 1) n = NUM2LONG(argv[0]); return rb_str_append(strftimev("%Y-%m-%d", self, set_tmx), iso8601_timediv(self, n)); }
傳回 JIS X 0301 格式的字串。選用參數 n
是小數秒的位數。
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9) #=> "H13.02.03T04:05:06.123456789+07:00"
static VALUE dt_lite_jisx0301(int argc, VALUE *argv, VALUE self) { long n = 0; rb_check_arity(argc, 0, 1); if (argc >= 1) n = NUM2LONG(argv[0]); return rb_str_append(d_lite_jisx0301(self), iso8601_timediv(self, n)); }
傳回範圍 (0..59) 內的分鐘。
DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5
static VALUE d_lite_min(VALUE self) { get_d1(self); return INT2FIX(m_min(dat)); }
複製 self 並重設其偏移量。
d = DateTime.new(2001,2,3,4,5,6,'-02:00') #=> #<DateTime: 2001-02-03T04:05:06-02:00 ...> d.new_offset('+09:00') #=> #<DateTime: 2001-02-03T15:05:06+09:00 ...>
static VALUE d_lite_new_offset(int argc, VALUE *argv, VALUE self) { VALUE vof; int rof; rb_scan_args(argc, argv, "01", &vof); rof = 0; if (argc >= 1) val2off(vof, rof); return dup_obj_with_new_offset(self, rof); }
傳回偏移量。
DateTime.parse('04pm+0730').offset #=> (5/16)
static VALUE d_lite_offset(VALUE self) { get_d1(self); return m_of_in_day(dat); }
此方法等於 strftime(‘%FT%T%:z’)。選用參數 n
是小數秒的位數。
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9) #=> "2001-02-03T04:05:06.123456789+07:00"
static VALUE dt_lite_rfc3339(int argc, VALUE *argv, VALUE self) { return dt_lite_iso8601(argc, argv, self); }
傳回範圍 (0..59) 內的秒數。
DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6
static VALUE d_lite_sec(VALUE self) { get_d1(self); return INT2FIX(m_sec(dat)); }
傳回秒數在範圍 (Rational(0, 1)…Rational(1, 1)) 中的分數部分
DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2)
static VALUE d_lite_sec_fraction(VALUE self) { get_d1(self); return m_sf_in_sec(dat); }
傳回 `self` 的字串表示形式,格式依照指定的 +format
DateTime.now.strftime # => "2022-07-01T11:03:19-05:00"
對於其他格式,請參閱 日期和時間格式
static VALUE dt_lite_strftime(int argc, VALUE *argv, VALUE self) { return date_strftime_internal(argc, argv, self, "%Y-%m-%dT%H:%M:%S%:z", set_tmx); }
傳回表示 `self` 的 Date
物件。
static VALUE datetime_to_date(VALUE self) { get_d1a(self); if (simple_dat_p(adat)) { VALUE new = d_lite_s_alloc_simple(cDate); { get_d1b(new); bdat->s = adat->s; bdat->s.jd = m_local_jd(adat); return new; } } else { VALUE new = d_lite_s_alloc_simple(cDate); { get_d1b(new); copy_complex_to_simple(new, &bdat->s, &adat->c); bdat->s.jd = m_local_jd(adat); bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT); return new; } } }
傳回 `self`。
static VALUE datetime_to_datetime(VALUE self) { return self; }
傳回表示 `self` 的 JSON
字串
require 'json/add/datetime' puts DateTime.now.to_json
輸出
{"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}
# File ext/json/lib/json/add/date_time.rb, line 62 def to_json(*args) as_json.to_json(*args) end
傳回 ISO 8601 格式的字串。(此方法不使用擴充表示形式。)
DateTime.new(2001,2,3,4,5,6,'-7').to_s #=> "2001-02-03T04:05:06-07:00"
static VALUE dt_lite_to_s(VALUE self) { return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx); }
傳回表示 `self` 的 Time
物件。
static VALUE datetime_to_time(VALUE self) { get_d1(self); if (m_julian_p(dat)) { self = d_lite_gregorian(self); get_d1a(self); dat = adat; } { VALUE t; t = rb_funcall(rb_cTime, rb_intern("new"), 7, m_real_year(dat), INT2FIX(m_mon(dat)), INT2FIX(m_mday(dat)), INT2FIX(m_hour(dat)), INT2FIX(m_min(dat)), f_add(INT2FIX(m_sec(dat)), m_sf_in_sec(dat)), INT2FIX(m_of(dat))); return t; } }
此方法等於 strftime(‘%FT%T%:z’)。選用參數 n
是小數秒的位數。
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9) #=> "2001-02-03T04:05:06.123456789+07:00"
傳回時區。
DateTime.parse('04pm+0730').zone #=> "+07:30"
static VALUE d_lite_zone(VALUE self) { get_d1(self); return m_zone(dat); }