0

So I know how to create a listener for listening to changes of the phone date. But what I need is different. Let's say that the phone's default time zone is "Europe/Paris". I want to detect a date change in a time zone of my choise ("America/Los_Angeles" for example), therefore completely ignoring the phone's time zone. I searched everywhere but couldn't find anything. Is there an easy way to do this in android?

2 Answers2

1

Let's start with getting timestamp of current day's beginning (00:00). We'll save this timestamp into now variable. Note that this timestamp is in UTC+0, so we want to add some offset to this timestamp according to our timezone. For "Europe/Paris" this offset is 1 hour (UTC+1) which can be calculated as 1 * millisInHour. It means that new day in Paris starts at 23:00 UTC+0. Thus current day in Paris timezone started at now.time - offset and next day will start at now.time - offset + millisInDay. Summing it up:

val millisInHour = TimeUnit.HOURS.toMillis(1)
val millisInDay = TimeUnit.DAYS.toMillis(1)
val now = Date(System.currentTimeMillis() / millisInDay * millisInDay)
val offset = 1 * millisInHour
Timer("TimerThread").schedule(
    object : TimerTask() {
        override fun run() {
            Log.i("Timer", "New day in Paris!")
        }
    },
    Date(now.time - offset + millisInDay),
    millisInDay
)

You can also simply get timezone offset for your device according to it's settings:

val offset = TimeZone.getDefault().rawOffset

UPD

As @Ole V.V. said in his answer, it's also possible to use java.time library if your minSdk is 26 or higher (or ThreeTenABP otherwise). Then instead of creating Date manually (Date(now.time - offset + millisInDay)) you can use the following code

val zone = ZoneId.of("Europe/Paris")
val today: LocalDate = LocalDate.now(zone)
val startOfDayTomorrow: Instant = today.plusDays(1).atStartOfDay(zone).toInstant()
val date = Date.from(startOfDayTomorrow)

It will give you the benefit of correctly handling summer time as @Ole V.V. mentioned in comments below.

alexal1
  • 394
  • 3
  • 7
  • 1
    And when Paris goes on summer time (DST)? (Then the offset will be 2 hours, not 1; and you can have this taken care of automatically if you leave it it to the date-time library) – Ole V.V. Jan 31 '21 at 19:13
  • @OleV.V. well I didn't face this problem because I used `TimeZone.getDefault().rawOffset` in my code, which already gives offset in current (summer/winter) time. But you're right, thank you, I didn't know about this library before! – alexal1 Jan 31 '21 at 19:56
0

java.time through desugaring

Use java.time, the modern Java date and time API, for date and time work. Not least when it’s not perfectly trivial.

The first thing is to calculate when the date changes in the other time zone.

    ZoneId zone = ZoneId.of("America/Los_Angeles");
    LocalDate today = LocalDate.now(zone);
    Instant startOfDayTomorrow = today.plusDays(1).atStartOfDay(zone).toInstant();
    
    System.out.println(startOfDayTomorrow);

Output from this snippet was:

2021-02-01T08:00:00Z

Now use the Android alarm manager to set an alarm for the calculated point of time. See for example the question How to trigger app function with specific time in Android? [closed] linked to at the bottom.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both 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) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161