Time เป็น class ใน Ruby represent จุดเวลาเฉพาะ อ่านบทความนี้จบ จะรู้ทุกอย่างเป็น Ruby time wizard!
Topics covered:
- แปลง strings เป็น time objects
- แยก time เป็น components (day/hours/milliseconds...)
- ใช้ class
Date,DateTimeและTimeใน Ruby - Format time 任何你想要的方式
- หาความต่างระหว่าง 2
Timeobjects
มาเริ่มกัน!
The Ruby Time Class
ใช้ Time class represent เวลาและวันที่ Date มี 3 components:
- day
- month
- year
และ Time:
- hours
- minutes
- seconds
ข้อมูลเก็บเป็นจำนวนวินาทีนับจาก Epoch (Unix time) มี หลายวิธี initialize Time object:
- Current time:
Time.now - Unix timestamp +
atmethod - ให้ starting date เป็นตัวเลขให้
Time.new(format: year/month/day)
แบบนี้:
Time.now # 2018-10-19 15:43:20 +0200 Time.new(2018, 1, 1) # 2018-01-01 00:00:00 +0100 Time.at(15000000000) # 2017-07-14 04:40:00 +0200
ขอ component ใดก็ได้จาก time object เช่น day, month, hour:
t = Time.now puts t.day puts t.month puts t.hour
ยังขอได้ว่า date นี้ตรงวันไหนในสัปดาห์ เช่น "วันอาทิตย์ไหม?" predicate methods คืน true หรือ false
ตัวอย่าง:
t = Time.now puts t.monday? puts t.sunday? puts t.friday?
ลองดู!
Time Zones
Time object มี time zone ใช้ zone method เช็ก time zone abbreviation ถ้าอยากได้ time zone offset 用 utc_offset output เป็นวินาที หาร 3600 ได้ชั่วโมง
ตัวอย่าง:
t = Time.now t.zone # "CET" t.utc_offset / 3600 # 1
ได้ current time ใน UTC:
Time.now.utc
Ruby Time Formatting
Ruby format Time objects แบบเฉพาะโดย default แต่อาจอยาก format อื่น ที่ ปรับตัวตาม use case ข่าวดี! มี เมธอด ได้เกือบ format 任何你想要的 คือ strftime (format time) ใช้ string พร้อม format specifiers แทนที่ด้วยค่า คล้าย printf
ตัวอย่าง:
time = Time.new
time.strftime("%d/%m/%Y") # "05/12/2015"
time.strftime("%k:%M") # "17:48"
time.strftime("%I:%M %p") # "11:04 PM"
time.strftime("Today is %A") # "Today is Sunday"
time.strftime("%d of %B, %Y") # "21 of December, 2015"
time.strftime("Unix time is %s") # "Unix time is 1449336630"
เมธอดนี้ยืดหยุ่นมาก ได้ time แยก date, หรือ date สวยพร้อมปี วัน ชื่อเดือน
Strftime Format Table
| Format | คำอธิบาย |
|---|---|
| %d | วันของเดือน (01..31) |
| %m | เดือนของปี (01..12) ใช้ %-m สำหรับ (1..12) |
| %k | ชั่วโมง (0..23) |
| %M | นาที |
| %S | วินาที (00..60) |
| %I | ชั่วโมง (1..12) |
| %p | AM/PM |
| %Y | ปี |
| %A | วันของสัปดาห์ (ชื่อ) |
| %B | เดือน (ชื่อ) |
ข้อมูลเพิ่มเติม: https://strftime.net/ และ https://devdocs.io/ruby/time#method-i-strftime
Generating a Timestamp
สร้าง time-zone independent timestamp สำหรับ date specific events:
Time.now.to_i # 1549054305
Timestamp นี้เป็นวินาทีใน UTC (Coordinated Universal Time)
Time Difference (Addition และ Subtraction)
บางครั้งอยากเวลาในอนาคตหรืออดีต ไม่ใช่เวลาปัจจุบัน ทำ addition กับ time objects ได้! จำ internal representation เป็นวินาที:
# เพิ่ม 10 วินาที time = Time.new + 10
ได้ time object ตั้ง 10 วินาทีจากตอนนี้ เช็กว่าเวลานั้นผ่านไปยัง:
Time.new > time
อยากได้วันวาน คำนวณวินาทีในหนึ่งวัน:
# seconds * minutes * hours 60 * 60 * 24 # 86400
ลบจาก current date:
Time.now - 86400
ถ้าใช้ Rails ทำแบบนี้ได้:
Time.now - 1.day
The Date Class
Date class ไม่มี concept ของ minutes, seconds, hours เก็บทุกอย่างเป็นวัน ต้อง require 'date' ใช้ Date.today ได้ current date ไม่เหมือน time Date.new ไม่ใช่ alias ของ today จดจำไว้
Date.today # Current date Date.new # Returns a negative date
Date arithmetic คล้าย Time ต่างที่บวกลบวันแทนวินาที:
Date.today + 1 # เพิ่มหนึ่งวัน
Date ไม่รู้ hours, seconds, minutes ใช้ class นี้ตอนไม่ต้องการพวกนี้
Date & Time Parsing
Date.parse พยายาม parse string ที่ดูเหมือน date ใช้ heuristic algorithm detect input format บางครั้งให้ผลไม่ต้องการ
ตัวอย่าง:
Date.parse("10/10/2010") # -> 2010-10-10
Date.parse("September 3") # -> 2015-09-03
Date.parse("May I have a cup of coffee, please?") # -> 1 of May
ถ้าต้องการ strict ใช้ Date.iso8601 iso8601 date format: year-month-day ArgumentError exception ถ้า input invalid
ตัวอย่าง:
Date.iso8601("2018-10-01")
ใช้ Date.strptime กับ format specifiers กำหนด custom input format เอง specifiers เหมือน strftime
ตัวอย่าง:
Date.strptime("3 of September", "%d of %B") # 2015-09-03
Parse time 用 Time class ความหมาย: แปลง string '2018-01-01 00:00' เป็น Time object!
ตัวอย่าง:
require 'time'
Time.parse("September 20 18:00")
อยากให้ format input string เอง ใช้ strptime:
require 'time'
Time.strptime("1 of December 2017", "%d of %B %Y")
ความต่าง Time.parse และ Date.parse แค่ object ที่ได้กลับ (Time หรือ Date)
Date Constants
Date class มี constants ที่มีประโยชน์ เช่น array เดือนของปี และ array วันของสัปดาห์ เดือนเริ่ม index 1 mapping month number -> month name ตรงๆ วันเริ่ม Sunday แต่用 rotate ให้สัปดาห์เริ่ม Monday
Date::MONTHNAMES # (index 0 = nil) Date::DAYNAMES.rotate(1)
The DateTime Class
DateTime subclass ของ Date เก็บ seconds เพิ่มเติมนอกจาก dates
ตัวอย่าง:
require 'date' DateTime.superclass # Date DateTime.now # DateTime: 2018-10-15T16:06:39+02:00
ทั้ง Time และ DateTime ทำงานเดียวกันได้ ความต่างหลัก: Time implemented in C เร็วกว่า
Performance:
Comparison: Time: 2644596.6 i/s DateTime: 231634.8 i/s - 11.42x slower
ActiveSupport – Time & Date Methods
ถ้าใช้ Rails คุ้นเคย 3.days.ago เมธอดเหล่านี้ไม่มีใน pure Ruby เพิ่มโดย ActiveSupport component ของ Rails ไม่คืน Time หรือ Date แต่ custom ActiveSupport class
1.hour.to_i # 3600 1.day # ActiveSupport::Duration 3.days.ago # ActiveSupport::TimeWithZone
Time math ได้ tomorrow's date:
Time.now + 1.day
Rails-exclusive time methods อื่นๆ:
date = Time.current date.change(hour: 20) date.at_beginning_of_day
Formatting:
date = Date.today date.to_formatted_s(:short) # "16 Jul" date.to_formatted_s(:long) # "July 16, 2018"
โค้ดเมธอดเหล่านี้ simple ควรดู source code TimeWithZone ด้วย
สรุป
ในบทความนี้เรียนรู้ Time และ Date classes, parse และ format time ใน Ruby และใช้ ActiveSupport time extensions
ขอบคุณที่อ่าน!