简体   繁体   中英

Calendar returns wrong week

So I need to get time in milliseconds for Monday of this week and time in milliseconds of Sunday for this week and with code below it worked fine till I installed app on emulator and if I set time to Sunday it returns Jun 18 - Jun 24 , but on Samsung Galaxy s5 it returns Jun 11 - Jun 17 <- this is how it should show Am I doing something wrong?

getMondayTime method returns time in milliseconds for monday

private fun getMondayTime(): Long{
    val calendar = Calendar.getInstance()
    calendar.timeInMillis = System.currentTimeMillis()
    calendar.firstDayOfWeek = Calendar.MONDAY
    calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
    calendar.set(Calendar.HOUR_OF_DAY, 0)
    calendar.set(Calendar.MINUTE, 0)
    calendar.set(Calendar.SECOND, 0)
    calendar.set(Calendar.MILLISECOND, 0)

    return calendar.timeInMillis
}

getSundayTime returns time in milliseconds for sunday

private fun getSundayTime(): Long {
    val calendar = Calendar.getInstance()
    calendar.timeInMillis = System.currentTimeMillis()
    calendar.firstDayOfWeek = Calendar.MONDAY
    calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY)
    calendar.set(Calendar.HOUR_OF_DAY, 22)
    calendar.set(Calendar.MINUTE, 0)
    calendar.set(Calendar.SECOND, 0)
    calendar.set(Calendar.MILLISECOND, 0)

    return calendar.timeInMillis
}

Here I'm putting all this time into places

fun generateWeek(): Week{
    val format = SimpleDateFormat("MMM d", Locale.ENGLISH)
    val mondayTime = getMondayTime()
    val sundayTime = getSundayTime()

    val label = "${format.format(mondayTime)} - ${format.format(sundayTime)}"
    return Week(label, mondayTime, sundayTime)
}

java.time

I am sorry I cannot write Kotlin (if that's your language?) so I will have to trust you to translate from Java. The modern solution is:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMM d", Locale.ENGLISH);
    // Time zone is crucial for controlling which week we get.
    ZoneId zone = ZoneId.of("America/Lower_Princes");
    WeekFields wf = WeekFields.ISO; // Monday is first day of week
    LocalDate today = LocalDate.now(zone);
    ZonedDateTime mondayTime = today.with(wf.dayOfWeek(), 1).atStartOfDay(zone);
    ZonedDateTime sundayTime = today.with(wf.dayOfWeek(), 7)
            .atTime(LocalTime.of(22, 0))
            .atZone(zone);
    String label = mondayTime.format(dateFormatter) + " - " + sundayTime.format(dateFormatter);
    System.out.println("Label:                 " + label);
    System.out.println("Monday time in millis: " + mondayTime.toInstant().toEpochMilli());
    System.out.println("Sunday time in millis: " + sundayTime.toInstant().toEpochMilli());

Running just now (Monday) this printed:

Label:                 Jun 18 - Jun 24
Monday time in millis: 1529294400000
Sunday time in millis: 1529892000000

At time of writing it is still Sunday in very few time zones in the Pacific. So I also tried one of those:

    ZoneId zone = ZoneId.of("Pacific/Niue");

Then I got last week:

Label:                 Jun 11 - Jun 17
Monday time in millis: 1528714800000
Sunday time in millis: 1529312400000

So specifying the correct time zone is crucial for getting the week you want. I suspect that this was the issue in your question: if your emulator is set to using a time zone where it was already Monday when you ran your code, it would give you the coming week, as you observed.

I am using and recommending java.time , the modern Java date and time API.

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.

If you are opposed to depending on an external library, even a future-proof one like ThreeTenABP — I mean, it's developed by the same folks that developed java.time for Java and it only contains functionality that will also be included in core Java once you upgrade to API level 26 or higher — in that case you can probably solve your issue by passing the correct TimeZone object to the Calendar.getInstance(TimeZone) method (I haven't tried). TimeZone is one more of the outdated date and time classes.

Links

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM