Làm cách nào để biết ngày hôm nay có nằm trong phạm vi ngày không?


81

Tôi có một sự kiện với start_timeend_timevà muốn kiểm tra xem sự kiện có "đang diễn ra" hay không. Đó sẽ là để kiểm tra xem ngày hôm nay có nằm trong khoảng giữa hai ngày không.

Làm thế nào bạn sẽ làm điều này trong một chức năng?

Câu trả lời:


61

Sử dụng ===


Trên thực tế, có một nhà điều hành sẽ làm điều này. Tạo Rangevà so sánh Timecác đối tượng với nó bằng ===toán tử.

start   = Time.now.to_i

range   = start..(start + 2)
inside  = start + 1
outside = start + 3        # ok, now...

range === inside  # true
range === outside # false


Cập nhật sau bình luận-lũ lụt: Phiên bản này hoạt động tốt ở mọi nơi. (Trong Rails, trong Ruby 1 và trong Ruby 2.) irbVí dụ trước đó cũng hoạt động tốt nhưng ví dụ tương tác không phải lúc nào cũng được sao chép chính xác trong một số thử nghiệm. Cái này dễ cắt và dán hơn.

Tất cả đã được giải quyết ngay bây giờ.


1
Không hoạt động trong Rails 3 trên Ruby 1.8.7, Vì vậy, tôi thích câu trả lời @heathd hơn.
Sandro L

3
Nhận được lỗi loại: Không thể lặp theo thời trong ruby 2.0
Pencilcheck

3
Bắt ở đây là gì? Giống như hai nhận xét khác, tôi đã thử chính xác mã này và gặp lỗi tương tự. Tại sao 19 người bỏ phiếu cho câu trả lời này? Nó đã bao giờ hoạt động? câu trả lời của hethd không làm việc cho tôi.
Ryan Sandridge

Cũng không làm việc cho tôi. Có lẽ nó đã hoạt động trong một phiên bản cũ hơn, nhưng dường như không còn nữa.
stickj

2
Lưu ý: để điều này hoạt động, bạn cần chuyển đổi ngày .to_ivà sau đó được sử dụng ===để xem liệu chúng có nằm trong phạm vi hay không. IMO, .coverage?là một giải pháp tốt hơn cho các cuộc hẹn hò.
erroric

246

Trong Ruby 1.9.2 ===không hoạt động, tôi gặp lỗi:

irb(main):019:0> (Time.now .. (Time.now+1)) === Time.now
TypeError: can't iterate from Time
    from (irb):19:in `each'
    from (irb):19:in `include?'
    from (irb):19:in `include?'
    from (irb):19:in `==='
    from (irb):19
    from /opt/ruby192/bin/irb:12:in `<main>'

Thay vào đó hãy sử dụng #cover?:

irb(main):002:0> (Time.now..Time.now+4).cover?(Time.now)
=> true
irb(main):003:0> (Time.now..Time.now+4).cover?(Time.now+10)
=> false

Đây là điều tôi yêu thích ở ruby, bạn luôn khám phá ra một phương pháp tuyệt vời khác thực hiện công việc cho bạn!
daniel

Đẹp. Đúng thứ tôi cần. Không biết về cover?phương pháp
Ryan Rebo

1
Này làm việc với Datecũng(Date.yesterday..Date.tomorrow).cover?(Date.today) => true
Amit Patel

1
Ruby đẹp! .. Cảm ơn!
Ele

===hoạt động tốt trong Ruby 1.9.2. Bạn chỉ cần quên.to_i
DigitalRoss

37

Nếu bạn đang sử dụng Rails, bạn có thể sử dụng TimeWithZone#between?. Sau đó, bạn sẽ có một cái gì đó như thế này:

> start_time = Time.zone.parse('12pm')      => Thu, 26 Jul 2012 12:00:00 EDT -04:00
> end_time = start_time + 1.hour            => Thu, 26 Jul 2012 13:00:00 EDT -04:00
> inside = Time.zone.parse('12:30pm')       => Thu, 26 Jul 2012 12:30:00 EDT -04:00
> outside = Time.zone.parse('1:30pm')       => Thu, 26 Jul 2012 13:30:00 EDT -04:00
> inside.between?(start_time, end_time)     => true
> outside.between?(start_time, end_time)    => false

17

Bởi vì lớp ngày bao gồm mô-đun So sánh được, mọi đối tượng ngày đều có một between?phương thức.

require 'date'

today           = Date.today
tomorrow        = today + 1
one_month_later = today >> 1

tomorrow.between?(today, one_month_later) # => true

Giờ học cũng vậy.
adass

Đây là cách dễ đọc hơn câu trả lời được chấp nhận. 1 cho việc sử dụng quyền hạn của Ruby đúng :)
thutt

5

Nếu bạn đang sử dụng Rails, bạn có thể thử cách này:

ruby-1.8.7-p299 :015 > a = DateTime.now
 => Fri, 02 Dec 2011 11:04:24 -0800 
ruby-1.8.7-p299 :016 > (a.beginning_of_day..a.end_of_day).include_with_range? a
 => true 
ruby-1.8.7-p299 :017 > (a.beginning_of_day..a.end_of_day).include_with_range? a+10.days
 => false 
ruby-1.8.7-p299 :018 > (a.beginning_of_day..a.end_of_day).include_with_range? a+25.hours
 => false 
ruby-1.8.7-p299 :019 > (a.beginning_of_day..a.end_of_day).include_with_range? a+2.hours
 => true 

Lưu ý: Tôi chỉ mới sử dụng beginning_of_dayend_of_dayđể cung cấp một phạm vi dễ dàng. Phần quan trọng là include_with_range?phương thức trên một Phạm vi.


Có vẻ như Phạm vi # include_with_range? do ActiveSupport cung cấp chỉ cần thêm khả năng kiểm tra xem một dải ô có bao gồm một dải ô khác hay không bằng cách sử dụng #include ?, ví dụ: (1..5) .include? (1..5). Ngoài ra, nó hoạt động giống hệt bản gốc của Ruby bao gồm? phương pháp. Vì đối số của bạn không phải là một phạm vi khác, nên phần mở rộng ActiveSupport này sẽ không có gì khác biệt. Trong mọi trường hợp, bạn chỉ nên gọi bao gồm? và không include_with_range? vì include_with_range? chỉ đơn giản là một bí danh để bao gồm? (sử dụng alias_method_chain).
Tyler Rick

a = DateTime.now; (a.beginning_of_day..a.end_of_day) .include_with_range? (a) trả về false cho tôi (không đúng) khi tôi thử nó trong bảng điều khiển trong Rails 3.2.8 và ruby-1.9.3-p194. (a.beginning_of_day..a.end_of_day) .cover? (a) trả về true, tuy nhiên, vì vậy tôi sẽ chỉ sử dụng nó thay thế.
Tyler Rick

một điểm hợp lệ. không chắc tại sao tôi lại chọn sử dụng include_with_rangevì nó không phải là trường hợp một phạm vi được so sánh với một phạm vi. Có lẽ là một loại u não nào đó. Bắt tốt, cảm ơn @TylerRick. @heathd câu trả lời thực sự là câu trả lời tốt nhất.
đauns

3

Nếu chúng là dấu thời gian:

def in_progress?
  (start_time..end_time) .include? (time.now)
kết thúc

Đối với tôi trên 1.9.2, điều này đưa ra một lỗiTypeError: can't iterate from Time
Benjamin Oakes

3

Đã kiểm tra là ngày hiện tại giữa hai ngày. Sử dụng Ruby

currentDate = DateTime.now
start_date = "2017-03-31"
end_date = "2018-03-31"
currentDate.between?(start_date, end_date)

**Out Put Will be** true or false

2

tóm lược

  d1      = DateTime.parse('2018/04/01')
  d2      = DateTime.parse('2018/04/29')
  outside = DateTime.parse('2018/04/30')
  inside  = DateTime.parse('2018/04/15')

  # include?
  (d1...d2).include?(d1)      # true
  (d1...d2).include?(d2)      # false
  (d1...d2).include?(outside) # false
  (d1...d2).include?(inside)  # true

  (d1..d2).include?(d1)      # true
  (d1..d2).include?(d2)      # true
  (d1..d2).include?(outside) # false
  (d1..d2).include?(inside)  # true

  # ===
  (d1...d2) === d1      # true
  (d1...d2) === d2      # false
  (d1...d2) === outside # false
  (d1...d2) === inside  # true

  (d1..d2) === d1      # true
  (d1..d2) === d2      # true
  (d1..d2) === outside # false
  (d1..d2) === inside  # true

  # cover?
  (d1...d2).cover?(d1)      # true
  (d1...d2).cover?(d2)      # false
  (d1...d2).cover?(outside) # false
  (d1...d2).cover?(inside)  # true

  (d1..d2).cover?(d1)      # true
  (d1..d2).cover?(d2)      # true
  (d1..d2).cover?(outside) # false
  (d1..d2).cover?(inside)  # true

  # between?
  d1.between?(d1, d2)       # true
  d2.between?(d1, d2)       # true
  outside.between?(d1, d2)  # false
  inside.between?(d1, d2)   # true
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.