2010-10-29 33 views
17

khi người dùng đăng ký một trong các trang web của tôi để dùng thử miễn phí, tôi đặt hết hạn tài khoản là "14.days.from_now". Sau đó, trên trang chủ tôi thấy có bao nhiêu ngày họ đã còn lại, mà tôi nhận được với:Rails lần lẻ: "x days from now"

(user.trial_expires - Time.now)/86400 

(vì có 86400 giây trong một ngày, tức là 60 * 60 * 24)

Điều buồn cười là, điều này xuất hiện là hơn 14, do đó được làm tròn lên đến 15. Khi điều tra kỹ hơn trong bảng điều khiển, điều này xảy ra chỉ trong hai ngày trong tương lai (nếu bạn biết ý tôi là gì). ví dụ:

>> Time.now 
=> Fri Oct 29 11:09:26 0100 2010 
>> future_1_day = 1.day.from_now 
=> Sat, 30 Oct 2010 11:09:27 BST 01:00 
#ten past eleven tomorrow 

>> (future_1_day - Time.now)/86400 
=> 0.999782301526931 
#less than 1, what you'd expect right? 

>> future_2_day = 2.day.from_now 
=> Sun, 31 Oct 2010 11:09:52 GMT 00:00 
>> (future_2_day - Time.now)/86400 
=> 2.04162248861183 
#greater than 2 - why? 

Tôi nghĩ có thể đã xảy ra với múi giờ - tôi nhận thấy rằng thời gian từ 1.day giờ là BST và thời gian 2 ngày kể từ bây giờ là GMT. Vì vậy, tôi đã thử sử dụng giờ địa phương và có cùng kết quả!

>> future_2_day = 2.day.from_now.localtime 
=> Sun Oct 31 11:11:24 0000 2010 
>> (future_2_day - Time.now)/86400 
=> 2.04160829127315 
>> (future_2_day - Time.now.localtime)/86400 
=> 2.04058651585648 

sau đó tôi tự hỏi lớn như thế nào là sự khác biệt, và nó chỉ ra rằng nó chính xác một giờ ra. Vì vậy, nó trông giống như một số kỳ quặc múi giờ, hoặc ít nhất một cái gì đó để làm với múi giờ mà tôi không hiểu. Hiện tại múi giờ của tôi là BST (thời gian mùa hè của người Anh), một giờ sau UTC vào lúc này (cho tới ngày chủ nhật này vào thời điểm đó nó sẽ trở lại giống như UTC).

Giờ bổ sung dường như được giới thiệu khi tôi thêm hai ngày vào Thời gian.hãy: kiểm tra điều này. Tôi bắt đầu với Time.now, thêm hai ngày vào nó, trừ Time.now, sau đó trừ hai ngày của giây từ kết quả, và còn lại với một giờ. Nó chỉ xảy ra với tôi, trong một khoảnh khắc tát đầu, rằng điều này xảy ra BECAUSE đồng hồ quay trở lại vào buổi sáng chủ nhật: tức là lúc 11.20 vào sáng chủ nhật nó sẽ là hai ngày VÀ một giờ thêm từ bây giờ. Tôi sắp xóa tất cả bài đăng này, nhưng sau đó tôi nhận thấy điều này: tôi nghĩ 'ah, tôi có thể sửa lỗi này bằng cách sử dụng (24 * daynum) .hours thay vì daynum.days, nhưng tôi vẫn nhận được kết quả tương tự: ngay cả khi tôi sử dụng giây!

>> (Time.now + (2*24).hours - Time.now) - 86400*2 
=> 3599.99969500001 
>> (Time.now + (2*24*3600).seconds - Time.now) - 86400*2 
=> 3599.999855 

Vì vậy, bây giờ tôi lại bị nhầm lẫn. Làm thế nào bây giờ có thể cộng với hai ngày giá trị của giây, trừ đi bây giờ, trừ đi hai ngày trị giá giây là một giờ giá trị của giây? Trường hợp thêm giờ lẻn vào?

+0

Một giờ thêm có thể là ngày ánh sáng tiết kiệm có lẽ? – willcodejavaforfood

+0

Tôi không thể sao chép kết quả của bạn. Tôi nhận được '(future_2_day - Time.now)/86400 # => 1.99977137731481'. Tôi đang ở EST (Hoa Kỳ) và đồng hồ của chúng tôi làm _not_ quay lại trong thời gian này. Vì vậy, nó phải là một vấn đề DST. –

+0

DST cắn tôi vào mông hai lần một năm, mỗi năm. Bạn nghĩ tôi sẽ học. – DanSingerman

Trả lời

19

willcodejavaforfood đã nhận xét, điều này là do thời gian tiết kiệm ánh sáng ban ngày kết thúc vào cuối tuần này.

Khi thêm thời lượng ActiveSupport có một số mã trong đó để bù lại nếu thời gian bắt đầu bằng DST và thời gian kết quả không phải là (hoặc ngược lại).

def since(seconds) 
    f = seconds.since(self) 
    if ActiveSupport::Duration === seconds 
    f 
    else 
    initial_dst = self.dst? ? 1 : 0 
    final_dst = f.dst? ? 1 : 0 
    (seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f 
    end 
rescue 
    self.to_datetime.since(seconds) 
end 

Nếu bạn có 11:09:27 và thêm một số ngày bạn vẫn sẽ nhận được 11:09:27 vào ngày kết quả ngay cả khi DST đã thay đổi. Điều này dẫn đến thêm một giờ nữa khi bạn thực hiện các phép tính tính bằng giây.

Một vài ý tưởng:

  • Sử dụng phương pháp distance_of_time_in_words helper để cung cấp cho người dùng một dấu hiệu của bao lâu còn lại trong thử nghiệm của họ.
  • Tính hết hạn là Time.now + (14 * 86400) thay vì sử dụng 14.days.from_now - nhưng một số người dùng có thể cho rằng họ đã mất một giờ dùng thử.
  • Đặt các bản dùng thử hết hạn vào lúc 23:59:59 vào ngày hết hạn bất kể thời gian đăng ký thực tế.
+1

aha, tuyệt vời, cảm ơn mike. Tôi biết nó phải giống như thế. Tôi đã cố gắng thiết lập thời gian hết hạn sử dụng giây (xem cuối bài viết của tôi) nhưng có kết quả tương tự. Ngoài ra, khi tôi thử distance_of_time_in_words tôi nhận được một lỗi: "TypeError: ActiveSupport :: TimeWithZone không thể bị ép buộc vào Fixnum". time_ago_in_words hoạt động tốt. –

+0

Bạn tham số nào cho 'distance_of_time_in_words'? 'time_ago_in_words' chỉ là một trình bao bọc xung quanh' distance_of_time_in_words' với tham số thứ 2 được đặt thành 'Time.now' nghĩa là' distance_of_time_in_words (from_time, Time.now, include_seconds) ' – mikej

+1

Nó không phải là lỗi, nó là một tính năng. Tùy thuộc vào định nghĩa của bạn về tính năng. – Kelvin

8

Bạn có thể sử dụng lớp Date để tính số ngày giữa ngày hôm nay và ngày hết hạn.

expire_date = Date.new(user.trial_expires.year, user.trial_expires.month, user.trial_expires.day) 
days_until_expiration = (expire_date - Date.today).to_i 
+0

Ý tưởng hay, nhờ Jonas –

+3

'today = Date.new (now.year, now.month, now.day)' có thể được đơn giản hóa thành 'today = Date.today' –

5

Sử dụng since, ví dụ: 14.days.since.to_date

Các vấn đề liên quan