0

I am developing an app that has a feature called 'Tasks'. In tasks, the user has to complete several available tasks. Once a task has been completed, I want to disable the task for 15 hours. I am using Firebase to store the data, I am storing 'timestamp' as a child of every 'task'. The 'timestamp' gets updated every time a task is completed. Now when the user opens the 'tasks' screen in the app, I want to check for each task, if it has been 15 hours since it was last completed. I can't seem to figure out how to get the number of hours between the 'timestamp' and the present time. All I need is a hint/direction. Any help is greatly appreciated.

Danish Ajaib
  • 109
  • 1
  • 11
  • What is the data type of your timestamp in Firebase? I believe that good practice would be to use a data and time data type in UTC or a string in ISO 8601 format,for example `2018-05-14T06:59:45.238Z`. – Ole V.V. May 14 '18 at 06:58

3 Answers3

2

When you send timestamp on firebase then you send time millis. When you have current timestamp and one timestamp of firebase. Then you can easily figure out time difference between these two.

long mills = firebaseTimeStamp - System.currentTimeInMillis();
int hours = millis/(1000 * 60 * 60);
int mins = (mills/(1000*60)) % 60;

String diff = hours + ":" + mins; 

You can get current time in millis by various methods like

    System.currentTimeMillis();
    Calendar.getInstance().getTimeInMillis();
    new Date().getTime();
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
  • We have classes for that in the *java.time* package. No need to write the math yourself. For earlier Android before 26, see the *ThreeTen-Backport* & *ThreeTenABP* projects. – Basil Bourque May 14 '18 at 20:20
2

If your timestamp is stored as date and time in UTC:

    LocalDateTime firebaseDateTimeInUtc = LocalDateTime.of(2018, Month.FEBRUARY, 9, 16, 30);
    long hours = ChronoUnit.HOURS.between(
            firebaseDateTimeInUtc.atOffset(ZoneOffset.UTC),
            OffsetDateTime.now(ZoneOffset.UTC));
    System.out.println(hours);

Running just now this printed

2246

If your timestamp is a string in ISO 8601 format:

    String firebaseInstantString = "2018-02-09T16:29:46.789Z";
    long hours = ChronoUnit.HOURS.between(
            Instant.parse(firebaseInstantString), Instant.now());

Or if you are storing milliseconds since the epoch (this is low-level):

    long firebaseTimestampMillis = 1_518_193_786_789L;
    long hours = TimeUnit.MILLISECONDS.toHours(
            System.currentTimeMillis() - firebaseTimestampMillis);

In the first two snippets I am using java.time, the modern Java date and time API. You can use it on less-than-brand-new Android devices when you add ThreeTanABP to your Android project.

Links

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

tl;dr

Use the modern java.time classes for such work.

Duration.between(
    Instant.ofEpochMilli( firebaseMillis ) ,  // Parse count of milliseconds since 1970-01-01T00:00:00Z as a `Instant` object, a moment in UTC.
    Instant.now()                             // Capture the current moment in UTC.
)                                             // Returns a `Duration` object, a span of time unattached to the timeline.
.compareTo(                                   // The `compareTo` method implemented per the `java.lang.Comparable` interface.
    Duration.ofHours( 15 )                    // Specify your business rule of a fifteen hour limit.
)                                             // Returns an `int`, where zero means equal, over zero means greater-than, and under zero means lesser-than.
> 0                                           // Asking if our duration is over the limit of 15 hours. Returns a `boolean` primitive.

Notice how using these classes makes your code clear and more self-documenting.

java.time

While I do not use Firebase, googling indicates that a Firebase TIMESTAMP type is a long integer count of milliseconds since the Unix epoch of first moment of 1970 in UTC, 1970-01-01T00:00:00Z.

The modern java.time classes make this work quite simple.

Parse your count-of-milliseconds to an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant then = Instant.ofEpochMilli( firebaseMillis ) ;

Capture the current moment in UTC.

Instant now = Instant.now() ;

By the way, to record that Instant moment, ask for the count of milliseconds from Unix epoch.

long millisSinceEpoch = now.toEpochMilli() ;

Determine the elapsed time, represented as a Duration object, a span of time unattached to the timeline.

Duration d = Duration.between( then , now ) ;

Your goal is to compare that span of time to a target of 15 hours.

Duration limit = Duration.ofHours( 15 ) ;
boolean isOverLimit = ( d.compareTo( limit ) > 0 ) ;  // positive means greater-than, zero means equal, and negative means less-than.

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154