0

I wanted to get the date of first day in current week. So I implemented it in this way:

fun getFirstDayInCurrentWeek(): Date {
    val calendar = Calendar.getInstance()
    calendar.clear(MILLISECOND)
    calendar.clear(SECOND)
    calendar.clear(MINUTE)
    calendar.set(HOUR_OF_DAY, 0)
    calendar.set(DAY_OF_WEEK, 1)
    return calendar.time
}

It works on most of the devices, but sometimes it returns the date of first day in next week. I can't figure it out why.

The classes come from java.util.*.

Edit: Just log the result of this function today (28.05.2018) and you will see either 27.05.2018 or 03.06.2018. The devices have the same locales and the same time zones.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Nominalista
  • 4,632
  • 11
  • 43
  • 102
  • Please provide some sample data so that test can be run against your results. – Barns May 28 '18 at 18:55
  • Just log the result of this function and you will see either 27.05.2018 or 03.05.2018 for today (28.05.2018). – Nominalista May 28 '18 at 19:15
  • Are you testing with devices having the same timezone/locale? That might explain the difference – user2340612 May 28 '18 at 20:18
  • In USA's locale, the first day of the week is `SUN`. Just like how "midnight" is for whatever reason `12:00 PM` instead of something like, say, `00:00`. – EpicPandaForce May 29 '18 at 00:10
  • @EpicPandaForce ok but there is 7 days difference in the result not only one day. – Nominalista May 29 '18 at 04:26
  • @user2340612 same locals and time zones – Nominalista May 29 '18 at 04:27
  • Thanks, Nominalista, for answering the questions asked in the comments. Please add the information in the question rather than in new comments. It’s easier to understand the question when we have everything in one place, and also comments are sometimes deleted, so don’t put important information there. – Ole V.V. May 29 '18 at 11:25

2 Answers2

2

If I understand correctly, you want to consider Sunday the first day of the week (as in USA).

    WeekFields wf = WeekFields.SUNDAY_START;
    LocalDate today = LocalDate.now(ZoneId.of("Europe/Warsaw"));
    LocalDate firstDayOfThisWeek = today.with(wf.dayOfWeek(), 1);
    System.out.println(firstDayOfThisWeek);

I am writing Java code and trusting you to transform to Kotlin. Running today (Tuesday, May 29) this printed

2018-05-27

If instead you want Monday as first day of the week (as in Poland and as the international standard says), just use WeekFields.ISO instead of WeekFields.SUNDAY_START. If you want it to depend on locale, use for example WeekFields.of(Locale.forLanguageTag("pl-PL")).

Another and possibly clearer option is:

    LocalDate firstDayOfThisWeek = today
            .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));

In both cases I use java.time, the modern Java date and time API. I think that this is a nice example of where it provides for clearer code, which is often the case compared to the old date and time classes like Calendar.

What went wrong in your code?

As I understand the documentation, your code should give the Sunday of the current week. Calendar uses 1 for Sunday. You might have used calendar.set(DAY_OF_WEEK, SUNDAY) to obtain exactly the same. When I run it today, I get 27 May when using Sunday as first day of week and 3 June when using Monday as first day (which means Sunday is the last day of the week). The documentation is not very clear, though, and the Calendar class can be confusing. In any case, probably this was also what happened when you tried on different devices: they had different definitions of weeks. This may be possible even if they have the same locale if you can configure week definitions separately.

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • This is a great answer, appreciate it. So what you mean is that `Calendar` works great for the first day of current week while using US standard, but behaves weird on ISO standard and returns first day of next week, right? And I think I'll have to use DateTime from Java 8. – Nominalista May 29 '18 at 12:20
  • Thanks. It’s not exactly what I meant. In your code you asked for Sunday, so it gives you Sunday no matter if Sunday is the first day of the week or not. – Ole V.V. May 29 '18 at 12:30
  • You mean `calendar.set(DAY_OF_WEEK, 1)` this sets always Sunday? But it doesn't matter actually, the problem was that it returned 7 days difference, not 1 day. – Nominalista May 29 '18 at 12:48
  • Yes, a day of week of 1 always means Sunday. So the only way it could give two different results was to give two different Sundays, and they are necessarily 7 days apart (at least). – Ole V.V. May 29 '18 at 15:17
1

First day of week is different for different countries. If you want it to be the same for all users, you could pass a Locale to the Calendar.

Calendar currentCalendar = Calendar.getInstance(new Locale("en","UK"));

also from this answer, You can use the method setFirstDayOfWeek() to set the first day of the week. The method can only affect the return values of WEEK_OF_MONTH or WEEK_OF_YEAR. For DAY_OF_WEEK, it does nothing.

You can implement something like:

Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
int rec = cal.get(Calendar.WEEK_OF_MONTH);
System.out.println(rec);

Read more on the API HERE

Adib Faramarzi
  • 3,798
  • 3
  • 29
  • 44