1

This is driving me nuts!

I have searched everywhere and found for example this question: How to get dates of a week (I know week number)?

However I can't get it to work in my implementation (On ANDROID API19 on NEXUS 7) :

public Pair<String,String> getWeekRange(int year, int week_no) {

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.WEEK_OF_YEAR, week_no);

    cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    Date monday = cal.getTime();
    cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
    Date sunday = cal.getTime();

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    return new Pair<String,String>(sdf.format(monday), sdf.format(sunday));
}   

For ANY call to getWeekRange(2014, WEEK) it ALWAYS gives me the date range of week 2 (which happens to be the current week number today) ??

Calendar seems to be a very confusing class, and there must be something I haven't understood. However according to the docs, YEAR, WEEK_OF_YEAR and DAY_OF_WEEK should be enough for me to set.

Some test data:
01-10 18:28:54.730: V/JSON(24503): Week 1/2014 is date range:2014-01-06 to 2014-01-12
01-10 18:28:54.730: V/JSON(24503): Week 2/2014 is date range:2014-01-06 to 2014-01-12
01-10 18:28:54.730: V/JSON(24503): Week 3/2014 is date range:2014-01-06 to 2014-01-12
01-10 18:28:54.730: V/JSON(24503): Week 4/2014 is date range:2014-01-06 to 2014-01-12
01-10 18:28:54.740: V/JSON(24503): Week 5/2014 is date range:2014-01-06 to 2014-01-12
01-10 18:28:54.740: V/JSON(24503): Week 1/2013 is date range:2013-01-07 to 2013-01-13
01-10 18:28:54.740: V/JSON(24503): Week 2/2013 is date range:2013-01-07 to 2013-01-13
01-10 18:28:54.740: V/JSON(24503): Week 3/2013 is date range:2013-01-07 to 2013-01-13
01-10 18:28:54.740: V/JSON(24503): Week 4/2013 is date range:2013-01-07 to 2013-01-13
01-10 18:28:54.740: V/JSON(24503): Week 5/2013 is date range:2013-01-07 to 2013-01-13

Can anyone see my mistake? Any help is appreciated.

** EDIT **

Seems that the code works fine on Windows, this is an isolated Android issue.

Community
  • 1
  • 1
Peter Andersson
  • 1,947
  • 3
  • 28
  • 44
  • 4
    Your code works perfectly without much change ([link to ideone](http://ideone.com/OfWIVp)). All I did was making the function `static`, and changing it to print the output rather than returning a `Pair`. – Sergey Kalinichenko Jan 10 '14 at 17:53
  • I have to agree with dasblinkenlight here. Your code looks ok and works as expected when I test it. Are you sure that you are actually testing the posted code and not something else? Which Java version are you using? – jarnbjo Jan 10 '14 at 17:57
  • Yes the java.util.Calendar and Date classes are confusing. Avoid them both. They are so bad that they are being supplanted in Java 8 by the new java.time.* classes defined by JSR 310 and inspired by [Joda-Time](http://www.joda.org/joda-time/) library. Until you can move to Java 8, use Joda-Time. – Basil Bourque Jan 10 '14 at 18:13
  • As you see above I have added an edit that this error only occurs on Android / Nexus 7. Should of course have mentioned this in the beginning but I kind of lost track. – Peter Andersson Jan 10 '14 at 21:58

3 Answers3

4

Writing this question made me read the docs once again, and just on a hunch I swapped the ordering so the function now looks like this:

public Pair<String,String> getWeekRange(int year, int week_no) {

    Calendar cal = Calendar.getInstance();

    cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.WEEK_OF_YEAR, week_no);
    Date monday = cal.getTime();

    cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.WEEK_OF_YEAR, week_no);
    Date sunday = cal.getTime();

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    return new Pair<String,String>(sdf.format(monday), sdf.format(sunday));
}

Lo and behold, it now gives me the correct dates.... It must be something with the internal implementation of Calendar that I dont understand.

Still don't know if the redundant lines are necessary, but for now I'm happy that it works!

Peter Andersson
  • 1,947
  • 3
  • 28
  • 44
  • 2
    You could use cal.add(Calendar.Date, 6) to get Sunday. That would save you 3 lines :-). – Sashi Jan 10 '14 at 18:06
2

I think that it's much better to use Joda-Time for such operations:

public Pair<String,String> getWeekRange(int year, int week_no) {
    DateTime startOfWeek = new DateTime().withYear(year).withWeekOfWeekyear(week_no);

    DateTime endOfWeek = startOfWeek.plusDays(6);

    return new Pair<String,String>(startOfWeek.toString(), endOfWeek.toString());
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Jakub Kubrynski
  • 13,724
  • 6
  • 60
  • 85
  • It seems that you are calculating from "today" rather then Monday. If someone would like to calculate from Monday then beside `withYear(year)` he should also add `.withDayOfWeek(1)`. Anyway +1 for Joda. – Pshemo Jan 10 '14 at 18:15
  • Besides the comment of @Pshemo about adding `.withDayOfWeek(1)` I have to remember that Joda Time is unfortunately only working with ISO-week starting on Monday. For Europe this is quite okay, but in US this is a no-go. Java 8 (and my time library) will do this much better. – Meno Hochschild Jan 10 '14 at 21:26
  • The problem in this question is actually one of the good reasons *not* to use Joda. Joda has no support for localized week rules, which is not only problematic when the first day of week differs from Monday, but the week-of-year numbering may also be wrong. – jarnbjo Jan 13 '14 at 13:22
1

Do it without importing Pair class

public  void getWeeksRangesDates(int y, int w) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.DAY_OF_MONTH, Calendar.MONDAY);
    cal.set(Calendar.YEAR, y);
    cal.set(Calendar.WEEK_OF_YEAR, w);
    Date date1 = cal.getTime();
    cal.add(Calendar.DATE, 6);
    Date date2 = cal.getTime();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    Log.v("date1",sdf.format(date1));
    Log.v("date2", sdf.format(date2));  
}
Komal12
  • 3,340
  • 4
  • 16
  • 25
Mohammad Adil
  • 503
  • 6
  • 13