<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Ruby中Date、Time、 DateTime這3個類提供 了和日期時間相關的操作。
Date只能處理日期
Time能處理日期和時間
DateTime也能處理日期和時間
其中,DateTime 是Date的一個子類,是對時間部分資料的補充。要使用Date和DateTime類,只需匯入date庫就可以,要使用Time類,匯入time庫就行。
require 'date' # 提供Date和DateTime類 require 'time' # 提供Time類(可直接使用,但匯入後有更多方法)
一般來說,操作日期時間的常用操作包括:
而這3個類中,都各自提供了一些方法,很多方法是重疊的。據我個人測試,DateTime這個標準庫效率是最高的。
下面,針對各種常見功能將這3個類結合在一起去介紹。
這3個類都能直接構造日期、時間物件。其中Date只能構造日期不能構造時間物件。
Date構造日期物件。如果提供了時間部分,則忽略時間部分。因為不涉及時間部分,所以不能也沒必要指定時區。
Ruby
# 1.構造當前日期物件:Date.today >> Date.today => #<Date: 2019-08-05 ((2458701j,0s,0n),+0s,2299161j)> >> puts Date.today 2019-08-05 # 2.構造指定日期:Date.new ## 可以構造超出2038年的日期 ## 如果沒有給定月、日,則預設為1 ## 如果沒有提供任何引數,預設是-4712年1月1日,這沒什麼意義 ## 如果給定時間部分,則報錯 >> Date.new(2018,3,20) => #<Date: 2018-03-20 ((2458198j,0s,0n),+0s,2299161j)> >> Date.new(2078,3,20) => #<Date: 2078-03-20 ((2480113j,0s,0n),+0s,2299161j)> >> Date.new(1900) => #<Date: 1900-01-01 ((2415021j,0s,0n),+0s,2299161j)> >> Date.new => #<Date: -4712-01-01 ((0j,0s,0n),+0s,2299161j)> # 3.構造指定日期:Date.parse ## 根據字串解析成日期格式 ## 如果給定時間部分,則忽略 ## 對於年份,可以給定1、2位數的和4位元數的 ## 對於1、2位數,如果數值是大於等於69的,則預設加上1900 ## 對於0和68之間的數值,則預設加上2000 >> Date.parse('2007/09/12') => #<Date: 2007-09-12 ((2454356j,0s,0n),+0s,2299161j)> >> Date.parse('2007/9/12') => #<Date: 2007-09-12 ((2454356j,0s,0n),+0s,2299161j)> >> Date.parse('2007-9-12') => #<Date: 2007-09-12 ((2454356j,0s,0n),+0s,2299161j)> >> Date.parse('2007-9-12 12:30:59') => #<Date: 2007-09-12 ((2454356j,0s,0n),+0s,2299161j)> >> Date.parse('08-9-12') => #<Date: 2008-09-12 ((2454722j,0s,0n),+0s,2299161j)> >> Date.parse('68-9-12') => #<Date: 2068-09-12 ((2476637j,0s,0n),+0s,2299161j)> >> Date.parse('69-9-12') => #<Date: 1969-09-12 ((2440477j,0s,0n),+0s,2299161j)> # 4.使用strptime方法根據給定格式的字串轉換成日期時間物件 ## 關於支援的格式,參見後文 >> Date.strptime('2001-02-03', '%Y-%m-%d') => #<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)> >> Date.strptime('02-03-2001', '%m-%d-%Y') => #<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>
常見的方法是:new(別名now)、at、local(別名mktime)、parse。
注:Time類沒有strptime方法將給定格式的字串轉換成日期時間物件。
# 1.new()或now()構建當前日期時間物件 ## new也可以根據給定引數構建日期時間物件,無參時等價於now ## 可以指定時區 >> Time.now => 2019-08-05 14:12:30 +0800 >> Time.new => 2019-08-05 14:12:31 +0800 >> Time.new(2007,11,6,17,10,0, "+08:00") # 指定時區 => 2007-11-06 17:10:00 +0800 # 2.at()將epoch轉換成日期時間物件 ## 支援時區,支援小數秒、毫秒、微秒、納秒 >> Time.at(1553488199) => 2019-03-25 12:29:59 +0800 >> Time.at(1553488199, in: '+08:00') # 指定時區 => 2019-03-25 12:29:59 +0800 >> Time.at(1553488199.3).usec # 小數秒0.3秒,即3毫秒 => 299999 >> Time.at(1553488199,123.345,:millisecond).usec # 毫秒引數 => 123344 >> Time.at(1553488199,123.345).nsec # 微秒引數 => 123344 >> Time.at(1553488199,123.345,:usec).nsec # 微秒引數 => 123344 >> Time.at(1553488199,123,:nsec).nsec # 納秒引數 => 123 # 3.mktime或local根據引數構建本地時區的日期時間物件 ## 要構建UTC時區時間,使用gm()或別名方法utc() ## mktime/local和gm/utc之間,除時區不同外,其它等價 >> Time.mktime(2009,10,23,14,3,6) => 2009-10-23 14:03:06 +0800 >> Time.mktime(2009,10,23) => 2009-10-23 00:00:00 +0800 >> Time.mktime(2009,10) => 2009-10-01 00:00:00 +0800 # 4.parse根據字串轉換成日期時間物件,同樣可以指定時區 >> Time.parse("2009/12/25 12:29:59") => 2009-12-25 12:29:59 +0800 >> Time.parse("2009/12/25") => 2009-12-25 00:00:00 +0800 >> Time.parse("2009/12") => 2009-12-01 00:00:00 +0800 >> Time.parse("2009/12/25 12:29:59 +00:00") # 指定時區 => 2009-12-25 12:29:59 +0000 >> Time.parse('2009-07-12 16:32:40.00123').nsec # 指定小數秒 => 1230000
由於上面介紹的幾種Time類方法構建出來的日期時間物件的時區預設是+08:00
(東八區,中國所在時區即東八),所以指定時區與否可隨意。
但下面DateTime類的幾種方法構造日期時間物件的時區預設是+00:00
,所以通常要指定時區。
DateTime是Date的子集,且由於某些方法被重寫,所以某些方法引數有一點點不同。最常使用的構造器是new、now、parse和strptime。
另外,DateTime物件是包含納秒的。
# 1.new()方法構造DateTime物件 ## 可以指定時區、指定小數秒 >> DateTime.new(2009,1,2,3,4,5) => #<DateTime: 2009-01-02T03:04:05+00:00 ((2454834j,11045s,0n),+0s,2299161j)> >> DateTime.new(2009,1,2,3,4,5,'+7') # 指定時區 => #<DateTime: 2009-01-02T03:04:05+07:00 ((2454833j,72245s,0n),+25200s,2299161j)> >> DateTime.new(2009,1,2,3,4,5,'+08:00') => #<DateTime: 2009-01-02T03:04:05+08:00 ((2454833j,68645s,0n),+28800s,2299161j)> >> DateTime.new(2009,1,2,3,4,5.3,'+08:00') # 指定小數秒,即毫秒 => #<DateTime: 2009-01-02T03:04:05+08:00 ((2454833j,68645s,300000000n),+28800s,2299161j)> >> DateTime.new(2009,1,2,3,4,5.3,'+08:00').sec_fraction => (3/10) # 2.now()獲取當前時間: >> DateTime.now => #<DateTime: 2019-08-05T15:00:42+08:00 ((2458701j,25242s,407854800n),+28800s,2299161j)> # 3.parse解析字串為日期時間物件 >> DateTime.parse('2009-12-20 12:03:30') => #<DateTime: 2009-12-20T12:03:30+00:00 ((2455186j,43410s,0n),+0s,2299161j)> >> DateTime.parse('2009-12-20 12:03:30 +8') => #<DateTime: 2009-12-20T12:03:30+08:00 ((2455186j,14610s,0n),+28800s,2299161j)> # 4.strptime解析給定格式的字串為日期時間物件 ## 關於支援的格式,參見後文 >> DateTime.strptime('2009-12-20 12:03:30 +8','%Y-%m-%d %H:%M:%S %z') => #<DateTime: 2009-12-20T12:03:30+08:00 ((2455186j,14610s,0n),+28800s,2299161j)>
構建日期時間物件時,有些日期、時間是無效的,但因為取值範圍的不同、特殊日期特殊時間點的取值不同,導致處理比較麻煩。
比如,每月可能有29、30、31天,但11月31號是無效的。再比如,秒數的範圍是在0-60,但第61秒僅作為閏秒時才是有效值,所以幾乎所有時間的第61秒都是錯誤的秒數。
Time可以檢測範圍外的無效時間,但是不能檢測範圍內的無效時間。比如Time知道11月32號是錯誤的,但它不知道11月31號是錯誤的,實際上Time會將有效範圍內超出的部分進位,比如11月31號進位到12月1號。
# 有效日期 >> Time.new(2007,11,30,17,10,30) => 2007-11-30 17:10:30 +0800 # 範圍內的無效日期,進位到12月1號 >> Time.new(2007,11,31,17,10,30) => 2007-12-01 17:10:30 +0800 # 有效秒 >> Time.new(2007,11,31,17,10,59) => 2007-12-01 17:10:59 +0800 # 第61秒進位到下一分鐘 >> Time.new(2007,11,31,17,10,60) => 2007-12-01 17:11:00 +0800 # 錯誤的秒,報錯 >> Time.new(2007,11,31,17,10,61) ArgumentError: sec out of range from (pry):25:in `initialize' # 錯誤的日期,報錯 >> Time.new(2007,11,32,17,10,59) ArgumentError: argument out of range from (pry):26:in `initialize'
Time會進位的特性有時候是有益的,但不利於檢測。好在,Date、DateTime可以很好的檢測無效的日期、時間,只要是無效的日期時間,它們都會報錯,其中Date只能檢測無效日期,DateTime可檢測無效日期,也能檢測無效時間。
# Date檢測無效日期 >> Date.new(2007,11,30) => #<Date: 2007-11-30 ((2454435j,0s,0n),+0s,2299161j)> >> Date.new(2007,11,31) ArgumentError: invalid date from (pry):28:in `initialize' # DateTime檢測無效日期、時間 >> DateTime.new(2007,11,31,11,12,13) ArgumentError: invalid date from (pry):31:in `new' >> DateTime.new(2007,11,30,11,12,60) ArgumentError: invalid date from (pry):32:in `new'
既然它們會報錯,那麼只要加上異常捕獲的程式碼即可完成日期時間的有效性檢測。比如在Time類中使用DateTime類來檢測有效的日期和時間:
class Time def self.valid?(y,m=1,d=1,H=0,M=0,S=0,us=0) require 'date' begin dt = DateTime(y,m,d,H,M,S,us) rescue returin nil end dt end end
這三個類的淵源:
所有有些時候有必要對它們進行型別的轉換。
這3個類都提供了下面3個方法,在各自之間進行轉換:
to_date to_time to_datetime
例如:
# Date物件轉換 >> Date.today.to_date => #<Date: 2019-08-05 ((2458701j,0s,0n),+0s,2299161j)> >> Date.today.to_time => 2019-08-05 00:00:00 +0800 >> Date.today.to_datetime => #<DateTime: 2019-08-05T00:00:00+00:00 ((2458701j,0s,0n),+0s,2299161j)> # Time物件轉換 >> Time.now.to_date >> Time.now.to_time >> Time.now.to_datetime # DateTime物件轉換 >> DateTime.now.to_date >> DateTime.now.to_time >> DateTime.now.to_datetime
需要注意,Date類物件由於不包含時間部分,它也沒有時區。所以:
d = Date.new(2019,5,23) d.to_time #=> 2019-05-23 00:00:00 +0800 d.to_datetime.to_s #=> "2019-05-23T00:00:00+00:00"
這是常用的需求。
日期時間物件還支援轉換成陣列。
先看Time型別物件,它支援to_s、to_f、to_i、to_r(轉分數)、to_a(轉陣列)。
# 轉字串 >> Time.now.to_s => "2019-08-05 15:29:49 +0800" # 轉數值,即整數epoch,和Time.at是相反的功能 >> Time.now.to_i => 1564990192 # 轉浮點數,即小數epoch ## 預設保留6位小數,即微秒級別 ## 可以格式化保留成納秒級別的字串 ## 但無法轉成納秒級別的浮點數,因為超出了float精度範圍 ## 可以使用BigDecimal儲存成科學記數法的浮點數 >> Time.now.to_f => 1564990197.671165 # 微秒 >> "%.9f" % Time.now.to_f => "1564990502.569714785" # 納秒字串 >> ("%.9f" % Time.now.to_f).to_f => 1564991500.1034229 # 超出,被剪掉 ## 使用BigDecimal儲存十進位制科學記數法浮點數 >> require 'bigdecimal' >> BigDecimal("%.9f" % Time.now.to_f) # 納秒浮點數 => 0.1564991123879058599e10 # 轉分數 >> Time.now.to_r => (3912475500217301/2500000) # 轉陣列 ## 10個陣列元素 ## [sec,min,hour,day,month,year,wday,yday,isdst,zone] ## [秒/分/時/日/月/年/週中天/年中天/是否夏令時/時區] >> Time.now.to_a => [4, 30, 15, 5, 8, 2019, 1, 217, false, "DST"]
注意,Time所檢視的時區以DST、CST、UTC、GMT這樣的方式顯示,而DateTime檢視的時區則是以類似於『+08:00』這種方式顯示。
再看Date和DateTime轉這些型別。其實Date/DateTime支援的轉換方法很少,它們只支援to_s
,其它方法都不支援。所以,要想轉成整數,可以先to_time,再to_i。
>> Date.today.to_s => "2019-08-05" >> Date.today.to_time => 2019-08-05 00:00:00 +0800 >> Date.today.to_time.to_i => 1564934400 >> DateTime.now.to_s => "2019-08-05T15:55:05+08:00" >> DateTime.now.to_time.to_f => 1564991712.1981702
strptime是將給定格式的字串轉成(解析成)日期時間物件,而strftime則是將日期時間轉成給定格式的字串。
Date、Time和DateTime這3個類都具有strftime。
>> d = Date.today >> d.strftime("%Y-%m-%d %H:%M:%S") => "2019-08-05 00:00:00" >> dt = DateTime.now >> dt.strftime("%Y-%m-%d %H:%M:%S") => "2019-08-05 16:00:03" >> t = Time.now >> t.strftime("%Y-%m-%d %H:%M:%S") => "2019-08-05 16:01:07"
其中百分號部分就是日期時間中的格式化字串預留位置。
另外,strftime和strptime所使用的格式是統一的。以下摘自官方手冊:strftime
%<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 - 4位元整數年份,可以是負數 %C - year / 100 (round down. 20 in 2009) %y - year % 100 (00..99) %m - 兩位數月份,不足時填充0(01..12) %_m blank-padded ( 1..12) %-m no-padded (1..12) %B - 英文名稱的月份全稱(January) %^B 大寫的月份全稱(JANUARY) %b - 簡寫月份名稱(Jan) %^b 大寫的月份簡寫(JAN) %h - 等價於%b %d - 兩位數月中天,不足時填充0(01..31) %-d no-padded (1..31) %e - 月中天,空格填充不足位數( 1..31) %j - 年中天,0填充(001..366) Time (Hour, Minute, Second, Subsecond): %H - 24-hour clock, zero-padded (00..23) %k - 24-hour clock, blank-padded ( 0..23) %I - 12-hour clock, zero-padded (01..12) %l - 12-hour clock, blank-padded ( 1..12) %P - lowercase(am or pm) %p - uppercase(AM or PM) %M - Minute of the hour (00..59) %S - Second of the minute (00..60) %L - 毫秒(000..999) %N - 小數秒,預設是9位小數,即納秒 %3N 毫秒millisecond (3 digits) %6N 微秒microsecond (6 digits) %9N 納秒nanosecond (9 digits) %12N 皮秒picosecond (12 digits) %15N femtosecond (15 digits) %18N attosecond (18 digits) %21N zeptosecond (21 digits) %24N yoctosecond (24 digits) Time zone: %z - 時區,從UTC開始偏移(例如:+0900) %:z - 時區,從UTC開始偏移,但帶一個冒號(+09:00) %::z - 時區,從UTC開始偏移,但帶兩個冒號(+09:00:00) %:::z - 時區,從UTC開始偏移,冒號隨意(+09,+09:30,+09:30:30) %Z - 等價於%:z (+09:00) Weekday: %A - 周幾的全稱(Sunday) %^A 大寫的周幾全稱(SUNDAY) %a - 周幾的簡稱(Sun) %^a 大寫的周幾簡稱(SUN) %u - 數值周幾(1..7),1表示週一(Monday is 1, 1..7) %w - 數值周幾(0..6),0表示週日(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 - epoch秒,即從1970-01-01 00:00:00 UTC距離現在已經過去的秒數 %Q - 毫秒epoch Literal string: %n - Newline character (n) %t - Tab character (t) %% - Literal ``%'' character Combination: 其中%F和%T常用 %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)
比如檢視一個日期中的年份、月份、分鐘、秒數、時區等資訊。
對於Date和DateTime物件,提供瞭如下幾個檢視各部分資訊的方法:
對於Time物件來說,除了上面幾個方法外(但不支援sec_fraction/second_fraction),它還支援直接檢視毫秒、微妙、納秒,即將小數秒轉換成對應的單位數值:
# DateTime >> dt = DateTime.new(2009,7,12,16,32,40.00123) >> dt.year #=> 2009 >> dt.mon #=> 7 >> dt.day #=> 12 >> dt.mday #=> 12 >> dt.cweek #=> 28 >> dt.hour #=> 16 >> dt.min #=> 32 >> dt.sec #=> 40 >> dt.sec_fraction #=> (123/100000) >> dt.yday #=> 193 >> dt.wday #=> 0 週日 >> dt.sunday? #=> true # DateTime: day_fraction >> DateTime.new(2009,7,12).day_fraction => (0/1) >> DateTime.new(2009,7,12,12).day_fraction => (1/2) >> DateTime.new(2009,7,12,16,32,40).day_fraction => (1489/2160) >> DateTime.new(2009,7,12,23,59,59).day_fraction => (86399/86400) >> DateTime.new(2009,7,12,16,32,40.00123).day_fraction => (5956000123/8640000000) # Time >> t = Time.parse('2009-07-12 16:32:40.00123') >> t.year #=> 2009 >> t.subsec #=> (123/100000) >> t.usec #=> 1230 >> t.nsec #=> 1230000
這是比較常見的需求,比如加7天之後的日期,10天前的日期等等。不過,對於Ruby來說,這些都很簡單,因為它已經實現好了相關的加減法運運算元以及一些相關的方法,非常方便。
Date/DateTime/Time都實現了+ -
操作,它們都返回新的日期時間物件:
下面是Date/DateTime類物件使用加減法進行日期運算的範例:
>> d = Date.parse('2019-02-26') >> dt = DateTime.parse('2019-02-26 12:30:30') >> d + 1 => #<Date: 2019-02-27 ((2458542j,0s,0n),+0s,2299161j)> >> d + 3 => #<Date: 2019-03-01 ((2458544j,0s,0n),+0s,2299161j)> >> d + 3 - 3 => #<Date: 2019-02-26 ((2458541j,0s,0n),+0s,2299161j)> >> (dt + 3).to_s => "2019-03-01T12:30:30+00:00" >> (dt + 2.5).to_s => "2019-03-01T00:30:30+00:00"
下面是Time類物件使用加減法進行時間運算的範例,注意秒運算可以是小數:
>> t = Time.new(2019,2,26,12,30,30) => 2019-02-26 12:30:30 +0800 >> t + 20 #=> 2019-02-26 12:30:50 +0800 >> t + 86400 #=> 2019-02-27 12:30:30 +0800 >> t + 86400 * 3 #=> 2019-03-01 12:30:30 +0800 >> (t + 10.32).nsec #=> 320000000
對於Date/DateTime類來說,還提供了月份運算的功能<< >>
:
<<
表示前幾個月,可以給負數來表示後幾個月>>
表示後幾個月,可以給負數來表示前幾個月>> dt.to_s # 2月26 => "2019-02-26T12:30:30+00:00" >> (dt << 1).to_s # 1月26 => "2019-01-26T12:30:30+00:00" >> (dt >> -1).to_s => "2019-01-26T12:30:30+00:00" >> (dt << -1).to_s # 3月26 => "2019-03-26T12:30:30+00:00" >> (dt >> 1).to_s => "2019-03-26T12:30:30+00:00"
但是,月份操作需要注意,有些月份的最後一天值是不一樣的,比如3月份最後一天是31日,向前移1個月是2月,2月最後一天可能是28日,也可能是29日。而對於月份操作來說,當運算後的月份的天數超出了該月範圍時,將自動取該月最後一天。
>> d = Date.new(2019,3,31) >> (d << 1).to_s => "2019-02-28"
這樣可能會導致一些意料之外的運算結果。例如,3月31號前移兩個月本是1月31號,但是通過兩次前移1個月,得到的將是1月28或1月29。
>> d = Date.new(2019,3,31) >> (d << 2).to_s #=> "2019-01-31" >> (d << 1 << 1).to_s #=> "2019-01-28" >> (d << 1 << -1).to_s #=> "2019-03-28"
所以,使用<< >>
來做月份運算是不安全的,如果要保證安全,還是儘量使用日期時間的加減法進行運算。
除了+ - << >>
這幾個運運算元,對於Date/DateTime來說還支援next/prev等一些操作:
當然,這些都能通過前面介紹的+ - << >>
來實現等價的。而且,對於month和year的操作,同樣有不安全的問題,參見上面對<< >>
的介紹。
Date/Time/DateTime都實現了<=>
運運算元,而且它們都mix-in了Comparable,所以可以直接進行大小比較,還可以使用between?這樣的方法來判斷某個時間點是否在時間範圍內。這是非常實用方便的功能。
此外,Date實現了===
運運算元,它等價於==
,所以只要日期相同,就返回true,而DateTime是Date的子類,所以,也適用於DateTime物件,儘管它們的時間部分可能不一樣。所以,Date和DateTime物件之間可以互相比較,但它們都不能直接於Time物件進行比較。
>> d1 = Date.new(2019,5,23) >> d2 = Date.new(2019,5,24) >> d1 < d2 #=> true >> dt1 = DateTime.new(2019,5,23,12,30,30.123) >> dt2 = DateTime.new(2019,5,23,12,30,30.234) >> dt1 < dt2 #=> true >> dt1 === dt2 #=> true,儘管時間不一樣,但結果true >> d1 === dt1 #=> true >> t1 = Time.new(2019,5,23,12,30,30.123) >> t2 = Time.new(2019,5,23,12,30,30.234) >> t1 === t2 #=> false >> t1 == t2 #=> false >> t1 < t2 #=> true
Date/DateTime還支援downto
和upto
兩種方式的日期迭代(Time不支援),預設每次迭代一天。
此外,還支援step迭代,它可以指定迭代時的步長。
>> d.to_s #=> "2019-03-31" >> (d+7).to_s #=> "2019-04-07" >> d.upto(d + 7) {|date| puts date} 2019-03-31 2019-04-01 2019-04-02 2019-04-03 2019-04-04 2019-04-05 2019-04-06 2019-04-07 >> (d + 7).downto(d) {|date| puts date} 2019-04-07 2019-04-06 2019-04-05 2019-04-04 2019-04-03 2019-04-02 2019-04-01 2019-03-31
對於step來說:
step(limit[, step=1]) → enumerator step(limit[, step=1]){|date| ...} → self
唯一需要注意的是,step語句塊返回的是原始物件,所以在語句塊中應當做出一些有意義的操作,並且不依賴於語句塊來構建返回值。
簡單的用法如下:
d = Date.new(2019, 5, 23) d1 = Date.new(2019, 5, 28) d.step(d1) { |date| puts date } puts "-" * 20 d.step(d1, 2) { |date| puts date }
輸出結果:
2019-05-23 2019-05-24 2019-05-25 2019-05-26 2019-05-27 2019-05-28 -------------------- 2019-05-23 2019-05-25 2019-05-27
Date/DateTime/Time這幾個類都有幾種構建日期時間物件的方式,但不同的構建方式,其效能肯定是有差別的。
下面測試這幾種方式構建100W個日期時間物件,來對比下它們的效能。
此處先說明結論:
Date只能構建日期物件,不包含時間,所以在某些場景下不太適合。
下面是構建100W個日期物件幾種方式的效率對比,從結果中可以看出,Date.new效率是最高的,Date.parse是最差的。
## Date.new $ time ruby -r'date' -e '1000000.times {|x| Date.new(2017,3,23)}' real 0m0.410s user 0m0.203s sys 0m0.203s ## Date.parse $ time ruby -r'date' -e '1000000.times {|x| Date.parse("2017-3-23")}' real 0m2.604s user 0m2.406s sys 0m0.219s ## Date.strptime $ time ruby -r'date' -e '1000000.times {|x| Date.strptime("2017-3-23","%Y-%m-%d")}' real 0m0.790s user 0m0.609s sys 0m0.203s
Time類構建100W個日期時間物件的幾種方式效率對比。從結果中可看出:
# Time類 ## Time.new,不指定時區 $ time ruby -r'time' -e '1000000.times {|x| Time.new(2017,3,23,16,30,15)}' real 0m2.546s user 0m0.969s sys 0m1.578s ## Time.new,指定時區 $ time ruby -r'time' -e '1000000.times {|x| Time.new(2017,3,23,16,30,15,"+08:00")}' real 0m0.663s user 0m0.453s sys 0m0.219s ## Time.at,不指定時區 $ time ruby -e '1000000.times {|x| Time.at(1490257815)}' real 0m0.358s user 0m0.141s sys 0m0.219s ## Time.at,指定時區 $ time ruby -e '1000000.times {|x| Time.at(1490257815,in: "+08:00")}' real 0m0.941s user 0m0.734s sys 0m0.219s ## Time.parse,指定時區 $ time ruby -r'time' -e '1000000.times {|x| Time.parse("2017-03-23 16:30:15 +0800")}' real 0m10.949s user 0m10.422s sys 0m0.531s ## Time.parse,不指定時區 $ time ruby -r'time' -e '1000000.times {|x| Time.parse("2017-03-23 16:30:15")}' real 0m10.972s user 0m8.953s sys 0m1.984s ## Time.mktime,指定時區 $ time ruby -r'time' -e '1000000.times {|x| Time.mktime(2017,3,23,16,30,15,"+08:00")}' real 0m2.575s user 0m0.984s sys 0m1.578s ## Time.mktime,不指定時區 $ time ruby -r'time' -e '1000000.times {|x| Time.mktime(2017,3,23,16,30,15)}' real 0m2.490s user 0m0.984s sys 0m1.531s
DateTime類構建100W個日期時間物件的幾種方式效率對比。從結果中可看出:
## DateTime.new:不指定時區 $ time ruby -r'date' -e '1000000.times {|x| DateTime.new(2017,3,23,16,30,15)}' real 0m0.409s user 0m0.219s sys 0m0.203s ## DateTime.new:指定時區 $ time ruby -r'date' -e '1000000.times {|x| DateTime.new(2017,3,23,16,30,15,"+08:00")}' real 0m0.502s user 0m0.328s sys 0m0.188s ## DateTime.strptime:不指定時區 $ time ruby -r'date' -e '1000000.times {|x| DateTime.strptime("2017-3-23 16:30:15","%Y-%m-%d %H:%M:%S")}' real 0m0.994s user 0m0.797s sys 0m0.219s ## DateTime.strptime:指定時區 $ time ruby -r'date' -e '1000000.times {|x| DateTime.strptime("2017-3-23 16:30:15 +08:00","%Y-%m-%d %H:%M:%S %z")} ' real 0m1.838s user 0m1.656s sys 0m0.203s ## DateTime.parse:不指定時區 $ time ruby -r'date' -e '1000000.times {|x| DateTime.parse("2017-3-23 16:30:15")}' real 0m6.206s user 0m5.984s sys 0m0.203s ## DateTime.parse:指定時區 $ time ruby -r'date' -e '1000000.times {|x| DateTime.parse("2017-3-23 16:30:15 +08:00")}' real 0m6.944s user 0m6.734s sys 0m0.203s
更多關於Ruby日期時間比較,Ruby日期轉換等Ruby時間日期處理方法請檢視下面的相關連結
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45