2012-03-19 25 views
6

Có ai biết về đá quý, phương pháp hoặc đoạn mã sẽ chuyển đổi giá trị datetime thành đôi khi thân thiện với con người hơn để tạo ra một loạt các quy tắc hoặc đặt một loạt các logic trong khung nhìn? Ví dụ: nếu hôm nay là 2012/03/19, chuyển đổi:Ruby/Rails: Chuyển đổi datetime thành ngôn ngữ tự nhiên (ví dụ: 3/23/2012 đến "Thứ Sáu này")

  • 3/23/2012 để “Đây Friday”
  • 2012/03/26 đến “Next Monday”
  • 3/31/2012 đến “cuối tuần Next”
  • 4/15/2012 để “tháng tới”
  • 3/15/2012 đến “cuối Thursday”
  • 3/01/2011 để “năm ngoái”

Về cơ bản, tôi đang tìm kiếm đối diện của Chronic gem. Một cái gì đó tương tự như distance_of_time_in_words, nhưng với một twist. Thay vì lấy ngày tháng từ cơ sở dữ liệu và hiển thị chúng dưới dạng, tôi muốn làm cho chúng trở nên thân thiện với con người hơn và dễ thấy hơn khi được hiển thị cho người dùng cuối.

+0

bạn muốn gì 2012/03/09 và 2012/04/06 để nói? – James

+0

Điều này sẽ là một người trợ giúp khá dễ dàng để viết, giả sử các quy tắc của bạn về cơ bản đơn giản như bạn trình bày, sau đó chỉ cần gắn nó vào application_helper.rb hoặc tạo một thư viện và bada-bing. Có vẻ vui - nếu tôi có một phút, tôi sẽ viết một số mã khởi động và đăng câu trả lời. –

+0

@ James- Tôi đoán "Tuần trước" và "Tháng tiếp theo", tương ứng. Bạn nghĩ điều gì sẽ phù hợp nhất nếu bạn đang trò chuyện với ai đó? Những phản hồi đó có làm cho việc tạo thuật toán lặp lại khó khăn hơn không? – Matt

Trả lời

5

Đây là một chút hack, hoàn toàn chưa hoàn thành và không phù hợp. Nhưng Ruby/Rails là rất tuyệt vời với ngày tháng, và phạm vi rất hoàn hảo, có lẽ nếu bạn không tìm thấy viên ngọc, một cái gì đó như thế này sẽ giúp bạn bắt đầu:

module HumanDate 
    def date_difference_for_people (from, to) 
    seconds_in_day = 24 * 60 * 60 
    days_difference = ((to - from)/seconds_in_day).round 
    case days_difference 
     when -1 
     "yesterday" 
     when 0 
     "today" 
     when 1 
     "tomorrow" 
     when 2..days_left_in_week 
     "this #{day_name(difference)}" 
     when (days_left_in_week + 1)..(days_left_in_week + 7) 
     "next week" 
     when (days_left_in_week + 8)..days_left_in_month 
     "later this month" 
     else 
     "later -- how much left to you :-)" 
    end 
    end 

    def day_name(days_from_now) 
    days_from_now.days_from_now.strftime("%A") 
    end 

    def days_left_in_month 
    Time.now.end_of_month.day - Time.now.day 
    end 

    def days_left_in_week 
    Time.now.end_of_week.day - Time.now.day 
    end 
end 
3

tôi sửa đổi Tom’s answer cho phù hợp với nhu cầu của tôi và được có thể sử dụng như một mô-đun độc lập mà không cần phải bao gồm nó ở bất cứ đâu. Tôi đã đặt tệp human_date.rb bên trong thư mục lib của mình. Tôi cũng đã khắc phục vấn đề khó khăn với tính toán days_difference.

module HumanDate 
    include ActionView::Helpers::DateHelper 
    extend self 

    def date_distance(from, to, long_form = true) 
    seconds_in_day = 60 * 60 * 24 
    days_difference = ((to.beginning_of_day.to_datetime - from.beginning_of_day.to_datetime)).floor 
    case days_difference 
     when -2 
     "day before yesterday" 
     when -1 
     "yesterday" 
     when 0 
     "today" 
     when 1 
     "tomorrow" 
     when 2..6 
     "this #{day_name(days_difference)}" 
     when 7..13 
     "next #{to.strftime("%a")} (#{short_date(days_difference)})" 
     else 
     if days_difference > 0 
      "in #{distance_of_time_in_words(from, to)} (#{short_date(days_difference, long_form)})" 
     else 
      "#{distance_of_time_in_words(from, to)} ago (#{short_date(days_difference, long_form)})" 
     end 
    end 
    end 

    def short_date(this_many, include_day=false) 
    format_string = "%-b %-d" 
    format_string = "%a, #{format_string}" if include_day 
    this_many.days.from_now.strftime(format_string) 
    end 

    def day_name(this_many) 
    this_many.days.from_now.strftime("%A") 
    end 

    def days_left_in_month 
    Time.now.end_of_month.day - Time.now.day 
    end 

    def days_left_in_week 
    Time.now.end_of_week.day - Time.now.day 
    end 
end 

Cách sử dụng:

1.9.3-p392 :001 > HumanDate. date_distance(Time.now, 2.day.ago) 
=> "day before yesterday" 
1.9.3-p392 :002 > HumanDate. date_distance(Time.now, 3.days.from_now) 
=> "this Tuesday" 
1.9.3-p392 :003 > HumanDate. date_distance(Time.now, 12.days.from_now) 
=> "next Thursday (Aug 1)" 
1.9.3-p392 :004 > HumanDate. date_distance(Time.now, 122.days.from_now) 
=> "in 4 months (Tue, Nov 19)" 
1.9.3-p392 :005 > HumanDate. date_distance(Time.now, 122.days.ago) 
=> "4 months ago (Wed, Mar 20)" 
+0

Đặc biệt dành cho người mới sử dụng Rails: Đặt tệp trong 'config/initializers'. Trên mẫu của bạn 'HumanDate.date_distance (Date.today, @ post.my_date)' –

0

Mục tiêu của đá quý Hublot là để giải quyết vấn đề này - trở thành một "ngược mãn tính".

https://github.com/brettshollenberger/hublot

câu hỏi liên quan: Ruby/Rails - Convert Date/Time back into Natural Language (2011-02-17 => February 17th, 2011)

+0

Vấn đề với đá quý Hublot (trong trường hợp này) là nó hoạt động trên datetime, không phải ngày. Vì vậy, bạn nhận được "Ngày mai lúc 12 giờ sáng" thay vì "Ngày mai". –

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