Cách tính ngày làm việc tiếp theo và trước đó trong Rails?Cách tính ngày tiếp theo, ngày làm việc trước đó trong Rails?
Trả lời
Theo như tôi hiểu, đây là những gì bạn đang tìm kiếm? (Thử nghiệm nó)
require 'date'
def next_business_day(date)
skip_weekends(date, 1)
end
def previous_business_day(date)
skip_weekends(date, -1)
end
def skip_weekends(date, inc)
date += inc
while (date.wday % 7 == 0) or (date.wday % 7 == 6) do
date += inc
end
date
end
Bạn có thể kiểm tra nó như sau:
begin
t = Date.new(2009,9,11) #Friday, today
puts "Today: #{Date::DAYNAMES[t.wday]} #{Date::MONTHNAMES[t.mon]} #{t.day}"
nextday = next_business_day(t)
puts "Next B-day: #{Date::MONTHNAMES[nextday.mon]} #{nextday.day}"
previousday = previous_business_day(nextday)
puts "back to previous: #{Date::MONTHNAMES[previousday.mon]} #{previousday.day}"
yesterday = previous_business_day(previousday)
puts "yesterday: #{Date::MONTHNAMES[yesterday.mon]} #{yesterday.day}"
end
Nếu ngày của bạn được đề cập là ngày chủ nhật, các câu hỏi trên không hoạt động và nếu bạn thử tăng 7 ngày từ chủ nhật, ngày đó sẽ được lặp lại vô hạn. – DavidNorth
@DavidNorth, nó hoạt động tốt. Ngày làm việc tiếp theo sau Chủ nhật có thể được coi là thứ hai hợp lý. Và có vẻ như bạn chỉ được phép vượt qua 1 hoặc -1 để skip_weekends, mà chỉ là một trợ giúp cho hai phương pháp khác. (Mặc dù nó sẽ tốt hơn nếu nó kiểm tra đối số không hợp lệ thay vì đi vào một vòng lặp vô hạn.) – antinome
Tôi đã vượt qua đối tượng Thời gian làm đối số và bị bỏ lại tự hỏi làm thế nào nó có thể mất hơn 1 giây để có được kết quả. Tôi nghĩ sẽ tốt hơn nếu bạn làm 'date + = inc.day' –
Vâng, bạn có thể sử dụng một cái gì đó như ngày hôm qua = 1.days.ago để nhận ngày hôm qua. Sử dụng hôm qua.ngày ('% w') để lấy ngày trong tuần làm số nguyên (0 = Chủ Nhật, 6 = Thứ Bảy). Nếu hôm qua là 0 (Chủ nhật), thì ngày hôm trước của tuần sẽ là 3.days.ago ... bạn có ý tưởng.
Và bạn có thể sử dụng ngày mai = 1.days.since để nhận ngày của ngày mai.
Dưới đây là hai ví dụ cho số ngày làm việc giữa hai ngày:
Dưới đây là một ngày lễ gói Ruby:
Bạn có thể cần phải tính toán ngày làm việc trong tương lai bắt đầu từ fr om một thứ bảy hoặc chủ nhật. 1 ngày làm việc sau Thứ Hai là Thứ Ba, 1 ngày làm việc kể từ Chủ Nhật cũng phải là Thứ Ba - ngày cuối tuần bắt đầu sẽ bị bỏ qua. Sau đây đạt được điều này:
class Date
def business_days_future(inc)
date = skip_weekend
inc.times do
date = date + 1
date = date.skip_weekend
end
date
end
# If date is a saturday or sunday, advance to the following monday
def skip_weekend
if wday == 0
self + 1
elsif wday == 6
self + 2
else
self
end
end
end
Điều này là tốt đẹp. Tôi sẽ đi với điều này. Cảm ơn. – juanpastas
Với holidays-gem bạn cũng có thể kiểm tra, nếu có một ngày nghỉ lễ. Nếu bạn làm như vậy, bạn phải xác định khu vực bạn cần. Ngày lễ-đá quý cũng cho phép sử dụng các tiểu vùng (ví dụ: us-va ...)
Mã ví dụ với ngày lễ Đức (de) và Mỹ-Mỹ (chúng tôi).
require 'holidays'
require 'holidays/us'
require 'holidays/de'
class Date
def next_business_day(region=:any)
skip_weekends_and_holidays(1,region)
end
def previous_business_day(region=:any)
skip_weekends_and_holidays(-1,region)
end
def skip_weekends_and_holidays(inc, region = :any)
date = self + inc
while (date.wday == 6 or date.holiday?(region)) do
date += inc
end
date
end
end
Lưu ý: skip_weekends_and_holidays
không tăng thêm ngày làm việc. Nếu bạn tăng 5 ngày từ Thứ Hai, bạn sẽ kết thúc vào Thứ Hai (trừ thứ Hai này không phải là ngày lễ). Nếu có một kỳ nghỉ trong 5 ngày, có tăng thêm.
Một số mã kiểm tra:
[
Date.new(2012,6,8), #Friday
Date.new(2012,6,10), #Monday
Date.new(2012,6,9), #Sunday
Date.new(2012,12,24), #Christmas eve
Date.new(2012,12,26), #After Christmas
].each{|t|
%w{us de}.each{|region|
puts "====#{region}======"
puts "Today: #{Date::DAYNAMES[t.wday]} #{Date::MONTHNAMES[t.mon]} #{t.day}"
nextday = t.next_business_day(region)
puts "Next B-day: #{Date::MONTHNAMES[nextday.mon]} #{nextday.day} - #{Date::DAYNAMES[nextday.wday]}"
previousday = t.previous_business_day(region)
puts "Previous B-day: #{Date::MONTHNAMES[previousday.mon]} #{previousday.day} - #{Date::DAYNAMES[previousday.wday]}"
}
Một chiết xuất từ kết quả (ngày trước giáng sinh):
====us======
Today: Monday December 24
Next B-day: December 26 - Wednesday
Previous B-day: December 23 - Sunday
Đức có hai ngày miễn phí (25 + 26,12):
====de======
Today: Monday December 24
Next B-day: December 27 - Thursday
Previous B-day: December 23 - Sunday
Cập nhật: Tôi đã tạo một phiên bản khác để xác định số nhân e ngày làm việc:
require 'holidays'
require 'holidays/us'
#~ require 'holidays/de'
class Date
def next_business_day(region=:any)
next_business_days(1,region)
end
def next_business_days(inc, region=:any)
date = self
inc.times{
date = date.next
while (date.wday == 6 or date.holiday?(region)) do
date = date.next
end
}
date
end
def previous_business_day(region=:any)
previous_business_days(1,region)
end
def previous_business_days(inc, region=:any)
date = self
inc.times{
date = date.prev_day
while (date.wday == 6 or date.holiday?(region)) do
date = date.prev_day
end
}
date
end
end
mã kiểm tra của tôi:
require 'test/unit'
class BDay_Test < Test::Unit::TestCase
def test_2012_06_08_us()
date = Date.new(2012, 6, 8)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('us'))
assert_equal(Date.new(2012, 06, 7), date.previous_business_day('us'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 05, 31), date.previous_business_day(7, 'us'))
end
def test_2012_06_08_de()
date = Date.new(2012, 6, 8)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('de'))
assert_equal(Date.new(2012, 06, 7), date.previous_business_day('de'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 05, 31), date.previous_business_day(7, 'de'))
end
def test_2012_06_10_us()
date = Date.new(2012, 6, 10)
assert_equal(Date.new(2012, 06, 11), date.next_business_day('us'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('us'))
assert_equal(Date.new(2012, 06, 18), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'us'))
end
def test_2012_06_10_de()
date = Date.new(2012, 6, 10)
assert_equal(Date.new(2012, 06, 11), date.next_business_day('de'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('de'))
assert_equal(Date.new(2012, 06, 18), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'de'))
end
def test_2012_06_09_us()
date = Date.new(2012, 6, 9)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('us'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('us'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'us'))
end
def test_2012_06_09_de()
date = Date.new(2012, 6, 9)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('de'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('de'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'de'))
end
def test_2012_12_24_us()
date = Date.new(2012, 12, 24)
assert_equal(Date.new(2012, 12, 26), date.next_business_day('us'))
assert_equal(Date.new(2012, 12, 23), date.previous_business_day('us'))
assert_equal(Date.new(2013, 01, 3), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 12, 16), date.previous_business_day(7, 'us'))
end
def test_2012_12_24_de()
date = Date.new(2012, 12, 24)
assert_equal(Date.new(2012, 12, 27), date.next_business_day('de'))
assert_equal(Date.new(2012, 12, 23), date.previous_business_day('de'))
assert_equal(Date.new(2013, 01, 4), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 12, 16), date.previous_business_day(7, 'de'))
end
def test_2012_12_26_us()
date = Date.new(2012, 12, 26)
assert_equal(Date.new(2012, 12, 27), date.next_business_day('us'))
assert_equal(Date.new(2012, 12, 24), date.previous_business_day('us'))
assert_equal(Date.new(2013, 01, 4), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 12, 17), date.previous_business_day(7, 'us'))
end
def test_2012_12_26_de()
date = Date.new(2012, 12, 26)
assert_equal(Date.new(2012, 12, 27), date.next_business_day('de'))
assert_equal(Date.new(2012, 12, 24), date.previous_business_day('de'))
assert_equal(Date.new(2013, 01, 4), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 12, 17), date.previous_business_day(7, 'de'))
end
end
Xem test_2012_12_24_us()
và date.next_business_days(7,...
Bạn kết thúc vào năm 2013, mỗi kỳ nghỉ trong kỳ được tôn trọng.
có thể đá quý này có thể hữu ích cho bạn câu hỏi
https://github.com/bokmann/business_time
này cho phép bạn tính toán giờ và ngày làm việc kể từ một ngày nhất định
Dưới đây là một phương pháp nhanh hơn mà sử dụng một phép tính đơn giản thay vì lặp lại trong những ngày.
class Time
def shift_weekdays(num_weekdays)
base = self
# corner case: self falls on a Sat or Sun then treat like its the next Monday
case self.wday
when 0
base = self + 1.day
when 6
base = self + 2.day
end
day_of_week = base.wday - 1 # Monday is 0
weekends = (day_of_week + num_weekdays)/5
base + (weekends*2).days + num_weekdays.days
end
end
Phương pháp này là trên lớp Thời gian nhưng có thể được sử dụng trên lớp ngày là tốt.
Tôi nhận ra rằng đây là một chủ đề cũ, nhưng tôi đã phải làm việc này cho bản thân mình và tôi đang tìm kiếm một đoạn mã rất ngắn để sửa đổi nếu một doanh nghiệp có ngày mở cửa kỳ lạ (như " đóng cửa chủ nhật/thứ hai ").
def next_business_day(from_day)
workdays = [1,2,3,4,5,6]
test_day = from_day + 1.day
return workdays.include?(test_day.wday) ? test_day : next_business_day(test_day)
end
Tôi cho rằng nó có thể được rút ngắn một lần nữa để một cái gì đó như thế này, nhưng tôi nghĩ rằng nó trở nên ít rõ ràng
def next_business_day(from_day)
test_day = from_day + 1.day
[1,2,3,4,5,6].include?(test_day.wday) ? test_day : next_business_day(test_day)
end
không cần trả lại dòng cuối cùng – piton4eg
Cảm ơn @ piton4eg, rút ngắn phiên bản ngắn hơn một chút. –
- 1. Ngày giờ Python - Ngày làm việc tiếp theo
- 2. Cách nhận ngày làm việc trước đó trong một tuần với ngày làm việc hiện tại bằng máy chủ sql
- 3. Tìm ba ngày làm việc trước đó từ một ngày cụ thể
- 4. Tính toán số ngày làm việc giữa hai ngày
- 5. Cách tính số ngày làm việc giữa hai ngày?
- 6. Nhận ngày tiếp theo từ ngày trong tuần trong JavaScript
- 7. Làm cách nào để tính toán ngày làm việc trước đó trong tập lệnh trình bao ksh?
- 8. LINQ - làm thế nào để có được ba ngày làm việc tiếp theo không kể ngày trong bảng?
- 9. Ngày làm việc/xử lý ngày lễ
- 10. Tính ngày làm việc gần nhất trong Postgres
- 11. Làm cách nào để biết ngày đó là 5 ngày trước?
- 12. Tải trước trang tiếp theo (hoặc trước đó) trong ViewPager
- 13. So sánh ngày của Rails; ngày lớn hơn hoặc bằng ngày trước
- 14. Ngày làm việc bằng Python
- 15. Cách tính 8 ngày làm việc kể từ ngày hôm nay?
- 16. PL/SQL Làm thế nào để có được X ngày trước từ một ngày như ngày?
- 17. Lấy ngày tháng đầu tiên và ngày cuối cùng của tháng trước đó trong C#
- 18. Cách nhận 30 ngày trước ngày hiện tại?
- 19. Cách tính giờ theo giờ giữa hai ngày trong iOS
- 20. Nhận ngày đầu tiên của tháng trước đó từ ngày hiện tại trong JavaScript
- 21. Làm cách nào để tìm dấu thời gian unix cho ngày bắt đầu của ngày tiếp theo trong php?
- 22. Làm cách nào để xác thực ngày như sau ngày hôm nay trong Rails?
- 23. làm cách nào để đảm bảo một ngày là ngày trong tuần trong Rails?
- 24. Ngày 180 ngày trước là gì?
- 25. Cách tìm ngày đầu tiên của tháng tiếp theo và các ngày còn lại cho đến ngày này với PHP
- 26. Làm cách nào tôi có thể làm việc với ngày trước 1900 trong PHP?
- 27. Xác nhận ngày trong Rails 3
- 28. git: ngày changelog theo ngày
- 29. Ngày nối tiếp trong SQL?
- 30. BeautifulSoup, Tìm th với văn bản 'giá', sau đó nhận được giá từ ngày tiếp theo
đang ngày lễ coi là một ngày làm việc? Có phải ngày làm việc chỉ là M-F không? –
chỉ M-F (ngày lễ được coi là ngày làm việc). nhưng nếu bạn có thể cho tôi để lọc ngày lễ sẽ tuyệt vời. –
Bạn đã thử làm điều đó chưa? Bạn nên thêm các lần thử mã trong câu hỏi của mình. – rogeriopvl