1

I'm creating a geofence in Android as shown in the Android documentation. The expiration duration in the example is 10 minutes, i.e. 600000 milliseconds.

geofenceList.add(new Geofence.Builder()
    .setRequestId("Victoria Station")
    .setCircularRegion(51.4954, -0.1443054, 500)
    .setExpirationDuration(600000)
    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
    .build());

public Geofence.Builder setExpirationDuration (long durationMillis)
Sets the expiration duration of geofence. This geofence will be removed automatically after this period of time.

Later I'm checking the entered values of the geofence like this

Geofence geofence = geofenceList.get(0);
Log.d(LOG_TAG, "expirationTime: " + geofence.getExpirationTime());

which results in an expirationTime of 525501519

public abstract long getExpirationTime ()
Returns the expiration elapsed realtime of geofence in milliseconds, or NEVER_EXPIRE if there's no expiration. When positive, this geofence will be removed automatically after that time.

How can I convert this expirationTime 525501519 into readable format?
Note: It is NOT a unix timestamp, which would be something like 1669823453000...

Taifun
  • 6,165
  • 17
  • 60
  • 188
  • Thank you @OleV.V., this looks great... do you like to convert this comment into an answer, so I can give you the bounty? – Taifun Dec 09 '22 at 00:35
  • 1
    Thanks for the confidence. I don’t otherwise write answers on Stack Overflow any more for reasons explained in [my profile](https://stackoverflow.com/users/5772882/ole-v-v). On your kind request I made an exception here. Do feel free to give the bounty to someone else if other answers to the same effect are posted. – Ole V.V. Dec 10 '22 at 10:05
  • 1
    @OleV.V. - Having experienced so many odds myself, I can feel your pain. TBH, even though we communicate almost every day via comments on Q&A, I checked your profile just now after approximately 1.5 years. While reading it, I felt like crying. God bless you! You have been selflessly contributing in so many ways. Please start posting answers. From 09-Nov-2021, I did not post anything for ten months but I did not see any change in those folks whom I was not happy with; so, I decided to come back again. – Arvind Kumar Avinash Dec 23 '22 at 17:54

2 Answers2

4

I don’t think it is well documented, but the time you get from GeoFence.getExpirationTime() is on the system clock’s elapsed real time (not measured from the epoch and also not meaning the time until expiration). So a conversion is needed.

Combining java.time, the modern Java date and time API, with the conversion found in another answer (links at the bottom), the following could be a way to obtain a human-readable wall-clock time of the geo-fence expiration.

The code is not tested because I haven’t got an Android development environment here, so forgive if there’s a typo.

Instant expiration = Instant.ofEpochMilli(
    System.currentTimeMillis()
        - SystemClock.elapsedRealTime()
        + geoFence.getExpirationTime()
);

ZonedDateTime expirationTime = expiration.atZone(ZoneId.systemDefault());
String expirationString = expirationTime
    .format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM));

System.out.println("Geo-fence expira a las: " + expirationString);

Example output:

Geo-fence expira a las: 04:05:52

From the documentation of SystemClock:

elapsedRealtime() and elapsedRealtimeNanos() return the time since the system was booted, and include deep sleep. This clock is guaranteed to be monotonic, and continues to tick even when the CPU is in power saving modes, so is the recommend basis for general purpose interval timing.

So this time is the right one for an expiration. The fence will expire 10 minutes after it’s been set no matter if the device goes to sleep in the meantime or the user tampers with the clock (on the other hand, the output from above code will relate to the Android clock and the time the user sees on that clock, which I take for desired).

DateTimeFormatter.ofLocalizedTime() implicitly relies upon the JVM’s current default Locale for producing the particular localized text, which is often a good bet for making users happy. If you want the time formatted differently, you can format the obtained ZonedDateTime in countless ways. Use the tutorial link at the bottom and/or search. If you are developing for older Android versions (under API level 26), the above code will require core library desugaring (link below).

Links

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

You need to convert long into readable format. Here is the simple and straight forward solution:

    long milliseconds = geofence.getExpirationTime();

    final long seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds);
    final long minute = TimeUnit.MILLISECONDS.toMinutes(milliseconds);
    final long hours = TimeUnit.MILLISECONDS.toHours(milliseconds);
    final long days = TimeUnit.MILLISECONDS.toDays(milliseconds);

    if(milliseconds < 1000){
        Log.d(LOG_TAG, days +"d:" +hours+"h:" +minute+"m:" +seconds +"s:" +milliseconds +"ms");
    }
    else{
        Log.d(LOG_TAG, days +"d:" +hours % 24 +"h:" +minute % 60 +"m:" +seconds % 60 +"s");
    }

As per your comment use below code to convert long in to 12hr time format (Also change timezone as per your need.):

    Date date = new Date(115218964);
    DateFormat formatter = new SimpleDateFormat("hh:mm a");
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    String dateFormatted = formatter.format(date);
Harsh Patel
  • 688
  • 2
  • 5
  • 16
  • Thank you for your answer. So if I create a geofence now using an expiration duration of `600000` milliseconds (i.e. 10 minutes), this results in an expirationTime of `115218964`, which is according to your calculation `1d:8h:0m:18s`. This result does not make any sense... it is now `1:23pm` in Costa Rica (which is GMT-6). My expectation is to get a result of `1:33pm` as expiration time (i.e. 10 minutes later than now)... – Taifun Dec 05 '22 at 19:28
  • Hi @Taifun . I just updated the answer hope it will help you. – Harsh Patel Dec 06 '22 at 04:49
  • Hi @Harsh Patel, thank you again, however unfortunately it does not help... as far as I can see, the result `115218964` is not a time in milliseconds... If I use the [time pattern](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html) `HH:mm:ss`, I get `08:00:18` as result, which does not make any sense... remember, `13:23` + 10 minutes would be `13:33`... and if I run a new test today at `19:41`, I get as result `224311831`, which results in `14:18:31`... remember, `19:41`+ 10 minutes would be `19:51`... – Taifun Dec 07 '22 at 01:45