2015-06-23 12 views
10

Tôi có thể thiếu một cái gì đó ở đây, nhưng tôi dường như không thể tìm thấy một lời giải thích trong tài liệu của Joda Time hoặc thực sự bất cứ nơi nào. Có vẻ như thời gian Joda bị phá vỡ khi tính toán tuần khi cộng và trừ các tuần khi bạn đi từ năm này sang năm khác.Joda Time minusweeks() và plusweeks() trong kỳ nghỉ giải lao năm 2014/2015?

Bất cứ ai có thể giải thích lý do tại sao điều này xảy ra và cách thực hiện đúng cách này?

tôi nhận được đầu ra sau đây từ mã của tôi dưới đây:

2015-01-08 - This is the current week 
2015-01-01 - Removed one week 
2014-12-25 - Removed one week 
2014-12-17 - Removed one week //for some reason, program backed 8 days here 
2014-12-10 - Removed one week 
2014-12-17 - Added one week 
2014-12-24 - Added one week 
2014-12-31 - Added one week 
2014-01-08 - Added one week //for some reason, program forwarded 8 days here, but it did not forward to 2015. 

gốc Mã

import org.joda.time.*; 

public class WonkyWeeks { 
    int year; 
    int week; 

    public void backUpOneWeek() { 
     LocalDate today = new LocalDate() 
       .withDayOfWeek(4) 
       .withWeekOfWeekyear(week) 
       .withYear(year); 
     LocalDate lastWeek = today.minusWeeks(1); 

     week = lastWeek.getWeekOfWeekyear(); 
     year = lastWeek.getYear(); 
     System.out.println(lastWeek+" - Removed one week"); 
    } 

    public void forwardOneWeek() { 
     LocalDate today = new LocalDate() 
       .withDayOfWeek(4) 
       .withWeekOfWeekyear(week) 
       .withYear(year); 
     LocalDate nextWeek = today.plusWeeks(1); 

     week = nextWeek.getWeekOfWeekyear(); 
     year = nextWeek.getYear(); 
     System.out.println(nextWeek+" - Added one week"); 
    } 

    public void thisWeek() { 
     LocalDate thisWeek = new LocalDate() 
       .withDayOfWeek(4) 
       .withWeekOfWeekyear(week) 
       .withYear(year); 
     System.out.println(thisWeek+" - This is the current week"); 
    } 

    public static void main(String[] args) { 
     WonkyWeeks wonky = new WonkyWeeks(); 
     wonky.week = 2; 
     wonky.year = 2015; 
     wonky.thisWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
    } 
} 

Sau khi thử nghiệm thêm nữa, nó được khó hiểu hơn. Tôi đã cố gắng thêm và xóa các ngày thay vì hàng tuần và vì lý do nào đó dường như bỏ qua ngày.

Output:

2015-01-08 - This is the current week 
2015-01-07 - removed one day 
2015-01-06 - removed one day 
2015-01-05 - removed one day 
2015-01-04 - removed one day 
2015-01-03 - removed one day 
2015-01-02 - removed one day 
2015-01-01 - Removed one full week 
2014-12-31 - removed one day 
2014-12-30 - removed one day 
2014-12-29 - removed one day 
2014-12-28 - removed one day 
2014-12-27 - removed one day 
2014-12-26 - removed one day 
2014-12-25 - Removed one full week 
2014-12-23 - removed one day // For some reason, it skipped 2014-12-24? 
2014-12-22 - removed one day 
2014-12-21 - removed one day 
2014-12-20 - removed one day 
2014-12-19 - removed one day 
2014-12-18 - removed one day 
2014-12-17 - Removed one full week 
2014-12-16 - removed one day 
2014-12-15 - removed one day 
2014-12-14 - removed one day 
2014-12-13 - removed one day 
2014-12-12 - removed one day 
2014-12-11 - removed one day 
2014-12-10 - Removed one full week 
2014-12-11 - added one day 
2014-12-12 - added one day 
2014-12-13 - added one day 
2014-12-14 - added one day 
2014-12-15 - added one day 
2014-12-16 - added one day 
2014-12-17 - Added one week 
2014-12-18 - added one day 
2014-12-19 - added one day 
2014-12-20 - added one day 
2014-12-21 - added one day 
2014-12-22 - added one day 
2014-12-23 - added one day 
2014-12-24 - Added one week 
2014-12-25 - added one day 
2014-12-26 - added one day 
2014-12-27 - added one day 
2014-12-28 - added one day 
2014-12-29 - added one day 
2014-12-30 - added one day 
2014-12-31 - Added one week 
2014-01-02 - added one day //Skipped 2014-01-01 and did not forward to 2015 
2014-01-03 - added one day 
2014-01-04 - added one day 
2014-01-05 - added one day 
2014-01-06 - added one day 
2014-01-07 - added one day 
2014-01-08 - Added one week 

Tiếp tục thử nghiệm mã

import org.joda.time.*; 

public class WonkyWeeks { 
    int year; 
    int week; 

    public void backUpOneWeek() { 
     LocalDate today = new LocalDate() 
       .withDayOfWeek(4) 
       .withWeekOfWeekyear(week) 
       .withYear(year); 
     LocalDate adayago = today.minusDays(1); 
     System.out.println(adayago+" - removed one day"); 
     LocalDate twodaysago = adayago.minusDays(1); 
     System.out.println(twodaysago+" - removed one day"); 
     LocalDate threedaysago = twodaysago.minusDays(1); 
     System.out.println(threedaysago+" - removed one day"); 
     LocalDate fourdaysago = threedaysago.minusDays(1); 
     System.out.println(fourdaysago+" - removed one day"); 
     LocalDate fivedaysago = fourdaysago.minusDays(1); 
     System.out.println(fivedaysago+" - removed one day"); 
     LocalDate sixdaysago = fivedaysago.minusDays(1); 
     System.out.println(sixdaysago+" - removed one day"); 
     LocalDate lastWeek = sixdaysago.minusDays(1); 

     week = lastWeek.getWeekOfWeekyear(); 
     year = lastWeek.getYear(); 
     System.out.println(lastWeek+" - Removed one full week"); 
    } 
    public void forwardOneWeek() { 
     LocalDate today = new LocalDate() 
       .withDayOfWeek(4) 
       .withWeekOfWeekyear(week) 
       .withYear(year); 
     LocalDate tomorrow = today.plusDays(1); 
     System.out.println(tomorrow+" - added one day"); 
     LocalDate dayAfterTomorrow = tomorrow.plusDays(1); 
     System.out.println(dayAfterTomorrow+" - added one day"); 
     LocalDate threeDaysFromNow = dayAfterTomorrow.plusDays(1); 
     System.out.println(threeDaysFromNow+" - added one day"); 
     LocalDate fourDaysFromNow = threeDaysFromNow.plusDays(1); 
     System.out.println(fourDaysFromNow+" - added one day"); 
     LocalDate fiveDaysFromNow = fourDaysFromNow.plusDays(1); 
     System.out.println(fiveDaysFromNow+" - added one day"); 
     LocalDate sixDaysFromNow = fiveDaysFromNow.plusDays(1); 
     System.out.println(sixDaysFromNow+" - added one day"); 
     LocalDate nextWeek = sixDaysFromNow.plusDays(1); 

     week = nextWeek.getWeekOfWeekyear(); 
     year = nextWeek.getYear(); 
     System.out.println(nextWeek+" - Added one week"); 
    } 
    public void thisWeek() { 
     LocalDate thisWeek = new LocalDate() 
       .withDayOfWeek(4) 
       .withWeekOfWeekyear(week) 
       .withYear(year); 
     System.out.println(thisWeek+" - This is the current week"); 
    } 
    public static void main(String[] args) { 
     WonkyWeeks wonky = new WonkyWeeks(); 
     wonky.week = 2; 
     wonky.year = 2015; 
     wonky.thisWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
    } 
} 
+0

tôi khuyên bạn nên gọt xuống mã ví dụ của bạn để xương trần của những gì cần thiết để tái tạo hành vi này. (có thể bạn sẽ khám phá ra một lỗi trong logic của riêng bạn trong khi bạn đang làm điều này) – bdares

+0

@bdares Làm thế nào nó có thể có thể được chia nhỏ hơn nữa? Tất cả các mã không là tạo ra một thể hiện của 'LocalDate', đặt nó vào thứ năm thứ hai của năm và sau đó cuộn trở lại và chuyển tiếp bằng cách sử dụng' cộng' và 'trừ' phương pháp được cung cấp bởi Joda? –

+0

Hay đúng hơn, nó tạo ra một vài trường hợp, nhưng tôi cũng nghĩ như vậy? –

Trả lời

2

Thời gian Joda đúng nhưng không phải là logic của bạn. Bạn phải cẩn thận tạo sự khác biệt giữa "năm dương lịch" (bắt đầu từ đầu tháng 1) và năm của ngày trong tuần (như được định nghĩa trong ISO-8601, còn được gọi là "tuần theo năm" hoặc đơn giản là "tuần -năm").

Ví dụ bạn sử dụng hai thành viên trong lớp học của bạn mà không được nghiêm chỉnh tương quan với nhau để lưu trữ kết quả trung gian:

week = nextWeek.getWeekOfWeekyear(); 
year = nextWeek.getYear(); 

Vấn đề với những dòng này là tuần có liên quan đến tuần based- năm, không phải năm dương lịch như dòng thứ hai chỉ ra. Hãy ghi nhớ rằng tuần dựa trên năm có thể là một năm ít hơn năm dương lịch vào đầu tháng Giêng. Ví dụ [2014-12-31] là cùng ngày với [2015-W01-3]. Cũng nên nhớ rằng Joda-Time cung cấp một phương thức khác gọi là getWeekyear().

Sau đó, bạn sẽ sử dụng hai giá trị này để thao tác một ngày theo cách này:

LocalDate today = new LocalDate() 
     .withDayOfWeek(4) 
     .withWeekOfWeekyear(week) 
     .withYear(year); 

Một lần nữa cùng một vấn đề thuật ngữ. Và phương pháp withWeekOfWeekyear(week) có thể đã thay đổi năm dương lịch và thay đổi ngày trong tháng sang một ngày khác khi cố gắng duy trì ngày trong tuần trong hiện tại năm 2015, không phải năm dương lịch 2014 tạo ra một ngày không mong muốn thay đổi! Toàn bộ mã tạo ra các kết quả không thực sự có thể đoán trước được và sẽ làm mọi người ngạc nhiên. Một vấn đề lớn khác là lệnh gọi của các cuộc gọi phương thức, điều quan trọng bởi vì thao tác tuần liên quan đến tuần hiện tại (cái nào ?!). Mã sau đây sẽ trông khỏe mạnh hơn nhiều:

LocalDate today = new LocalDate() 
     .withWeekyear(year) 
     .withWeekOfWeekyear(week) 
     .withDayOfWeek(4); 

Giải pháp: Bạn nên tham khảo tốt hơn do đó với tuần năm, chưa năm dương lịch trong mã của bạn. Hoặc thậm chí tốt hơn: Nếu bạn chỉ muốn thêm hoặc xóa tuần thì tôi đề nghị bạn lưu trữ ngày (làm đối tượng kiểu LocalDate) thay vào đó và áp dụng date.plusWeeks(1) hoặc tương tự. Bạn luôn có thể truy vấn ngày cho các ngày trong tuần, tuần trong tuần, năm dương lịch, năm dương lịch, vv .. Tốt hơn nhiều so với lưu theo năm và năm dương lịch.

Cập nhật sau khi thử nghiệm:

bây giờ tôi đã thay đổi năm đến tuần năm và cũng đã thay đổi thứ tự của phương pháp gọi khi thiết ngày (lần đầu tiên trong tuần năm, sau đó trong tuần và cuối cùng là ngày trong tuần). Sau khi những thay đổi này, mã của bạn sẽ hoạt động tốt theo các thử nghiệm của riêng tôi (mặc dù tôi vẫn khuyên bạn nên đơn giản hóa trạng thái lớp và logic của bạn). Ở đây toàn thay đổi và điều chỉnh mã của tôi:

import org.joda.time.LocalDate; 

public class WonkyWeeks { 
    int year; 
    int week; 

    public void backUpOneWeek() { 
     LocalDate today = 
      new LocalDate().withWeekyear(year).withWeekOfWeekyear(week).withDayOfWeek(4); 
     LocalDate adayago = today.minusDays(1); 
     System.out.println(adayago + " - removed one day"); 
     LocalDate twodaysago = adayago.minusDays(1); 
     System.out.println(twodaysago + " - removed one day"); 
     LocalDate threedaysago = twodaysago.minusDays(1); 
     System.out.println(threedaysago + " - removed one day"); 
     LocalDate fourdaysago = threedaysago.minusDays(1); 
     System.out.println(fourdaysago + " - removed one day"); 
     LocalDate fivedaysago = fourdaysago.minusDays(1); 
     System.out.println(fivedaysago + " - removed one day"); 
     LocalDate sixdaysago = fivedaysago.minusDays(1); 
     System.out.println(sixdaysago + " - removed one day"); 
     LocalDate lastWeek = sixdaysago.minusDays(1); 

     week = lastWeek.getWeekOfWeekyear(); 
     year = lastWeek.getWeekyear(); 
     System.out.println(lastWeek + " - Removed one full week"); 
    } 

    public void forwardOneWeek() { 
     LocalDate today = 
      new LocalDate().withWeekyear(year).withWeekOfWeekyear(week).withDayOfWeek(4); 
     LocalDate tomorrow = today.plusDays(1); 
     System.out.println(tomorrow + " - added one day"); 
     LocalDate dayAfterTomorrow = tomorrow.plusDays(1); 
     System.out.println(dayAfterTomorrow + " - added one day"); 
     LocalDate threeDaysFromNow = dayAfterTomorrow.plusDays(1); 
     System.out.println(threeDaysFromNow + " - added one day"); 
     LocalDate fourDaysFromNow = threeDaysFromNow.plusDays(1); 
     System.out.println(fourDaysFromNow + " - added one day"); 
     LocalDate fiveDaysFromNow = fourDaysFromNow.plusDays(1); 
     System.out.println(fiveDaysFromNow + " - added one day"); 
     LocalDate sixDaysFromNow = fiveDaysFromNow.plusDays(1); 
     System.out.println(sixDaysFromNow + " - added one day"); 
     LocalDate nextWeek = sixDaysFromNow.plusDays(1); 

     week = nextWeek.getWeekOfWeekyear(); 
     year = nextWeek.getWeekyear(); 
     System.out.println(nextWeek + " - Added one week"); 
    } 

    public void thisWeek() { 
     LocalDate thisWeek = 
      new LocalDate().withWeekyear(year).withWeekOfWeekyear(week).withDayOfWeek(4); 
     System.out.println(thisWeek + " - This is the current week"); 
    } 

    public static void main(String[] args) { 
     WonkyWeeks wonky = new WonkyWeeks(); 
     wonky.week = 2; 
     wonky.year = 2015; 
     wonky.thisWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.backUpOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
     wonky.forwardOneWeek(); 
    } 
} 

Output của mã thay đổi:

2015-01-08 - This is the current week 
2015-01-07 - removed one day 
2015-01-06 - removed one day 
2015-01-05 - removed one day 
2015-01-04 - removed one day 
2015-01-03 - removed one day 
2015-01-02 - removed one day 
2015-01-01 - Removed one full week 
2014-12-31 - removed one day 
2014-12-30 - removed one day 
2014-12-29 - removed one day 
2014-12-28 - removed one day 
2014-12-27 - removed one day 
2014-12-26 - removed one day 
2014-12-25 - Removed one full week 
2014-12-24 - removed one day 
2014-12-23 - removed one day 
2014-12-22 - removed one day 
2014-12-21 - removed one day 
2014-12-20 - removed one day 
2014-12-19 - removed one day 
2014-12-18 - Removed one full week 
2014-12-17 - removed one day 
2014-12-16 - removed one day 
2014-12-15 - removed one day 
2014-12-14 - removed one day 
2014-12-13 - removed one day 
2014-12-12 - removed one day 
2014-12-11 - Removed one full week 
2014-12-12 - added one day 
2014-12-13 - added one day 
2014-12-14 - added one day 
2014-12-15 - added one day 
2014-12-16 - added one day 
2014-12-17 - added one day 
2014-12-18 - Added one week 
2014-12-19 - added one day 
2014-12-20 - added one day 
2014-12-21 - added one day 
2014-12-22 - added one day 
2014-12-23 - added one day 
2014-12-24 - added one day 
2014-12-25 - Added one week 
2014-12-26 - added one day 
2014-12-27 - added one day 
2014-12-28 - added one day 
2014-12-29 - added one day 
2014-12-30 - added one day 
2014-12-31 - added one day 
2015-01-01 - Added one week 
2015-01-02 - added one day 
2015-01-03 - added one day 
2015-01-04 - added one day 
2015-01-05 - added one day 
2015-01-06 - added one day 
2015-01-07 - added one day 
2015-01-08 - Added one week 
+0

Rất tốt giải thích. Tôi đã cố gắng thu thập tất cả các thông tin trong câu trả lời của tôi nhưng không thể tìm thấy tốt hơn của bạn. +1 – TheCodingFrog

+0

Wow, lời giải thích thực sự tốt! Cảm ơn nhiều! Lên bầu và trả lời đúng! =) –

0

Tôi không thấy bất kỳ vấn đề với logic của bạn. Sau khi thử các kịch bản khác nhau và gỡ lỗi một số mã, tôi tin rằng đó là do hành vi của dayOfWeek cho các năm khác nhau.

Điều này có thể không cung cấp câu trả lời hoàn chỉnh cho vấn đề của bạn nhưng có thể cung cấp cho bạn gợi ý.

Bạn đang vượt qua 4th ngày trong tuần luôn không phân biệt trong năm. Nhưng nó đại diện cho những ngày khác nhau tùy thuộc vào năm. Ví dụ: Ví dụ: nếu bạn vượt qua day as 4, week 1 and year 2013 và sau đó gọi getDayOfWeek(), bạn sẽ nhận được giá trị là 2 (Thứ Ba).

Tương tự cho năm 2014, getDayOfWeek() sẽ trả lại 3 (Thứ Tư) và cho năm 2015, nó sẽ là 4 (Thứ Năm).

Vì vậy, trong năm 2015, Ngày trong tuần 4 đại diện cho Thursday trong đó tính đến năm 2014, nó đại diện cho Wednesday.

Hãy nhìn vào trường hợp sử dụng của bạn bây giờ:

  • 2015-01-08 - Đây là tuần hiện tại (tuần thứ 2, ngày thứ 4 - Thứ Năm).
  • 2015-01-01 - Đã xóa một tuần - (tuần thứ 1, ngày thứ 4 - thứ 5).
  • 2014-12-25 - Đã xóa một tuần - (tuần thứ 4, ngày thứ 4 - thứ 5).
  • 2014-12-17 - Đã xóa một tuần - (Hiệu chỉnh được thực hiện tại đây - tuần thứ 3, ngày thứ 4 - thứ tư).

Tôi không chắc chắn tại sao sửa không được thực hiện trên 2014-12-25.

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