27

I have a model with the following structure

public class OfferModel {
    private String mImageUrl;
    private String mOfferCode;
    private String mOfferTitle;
    private String mOfferDescription;
    private boolean mIsRunning;
    private String mCreatorUid;
    private Date mStartDate;
}

Everything else works fine on saving. It saves in Firebase Realtime database as

startDate
    date: 22
    day: 3
    hours: 23
    minutes: 20
    month: 5
    seconds: 50
    time: 1466617850476
    timezoneOffset: -330
    year: 116

But when I try to retrieve it, the date gives the following error -

java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.Date
at com.localvine.models.OfferModel.<init>(OfferModel.java:37)
at com.localvine.managers.OfferManager$1.onDataChange(OfferManager.java:62)
at com.google.android.gms.internal.zzafp.zza(Unknown Source)
at com.google.android.gms.internal.zzagp.zzSu(Unknown Source)
at com.google.android.gms.internal.zzags$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:615)

I understand that Firebase doesn't support Java Date object, but since it's saving them in a map, how can I get back the date from that map? Is there any proper way of saving and retrieving dates in Firebase Android?

0xC0DED00D
  • 19,522
  • 20
  • 117
  • 184

5 Answers5

22

You can store the date as an epoch date. It's a long that you can get using your system time System.currentTimeMillis(); or by using the Firebase server time with their ServerValue.TIMESTAMP. The thing with the first option is that it changes with timezones and system settings. So if you store the date as a long, you just have to change your OfferModel field mStartDate to a long and then use new Date(long) to get the corresponding Date when retrieving the object.

Sunshinator
  • 940
  • 11
  • 23
  • 1
    Actually, epoch time is the number of seconds since Jan 1 1970 UTC; What you are suggesting is to use the number of milliseconds – Greg Ennis May 22 '17 at 19:18
13

Use ISO 8601 date format:

SimpleDateFormat ISO_8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:sss'Z'");

String now = ISO_8601_FORMAT.format(new Date());

Representing Date as a String has two greater advantages:

  • It is human readable ("2018-03-30T13:18:39.516Z" vs 1522415925281)
  • At the browser side, you can simply invokes new Date("2018-03-30T13:18:39.516Z")

This is quite useful if you have Android and browsers both consuming Firebase data.

JP Ventura
  • 5,564
  • 6
  • 52
  • 69
  • 1
    In my case the pattern appeared to be ```yyyy-MM-dd'T'HH:mm:ss.SSS'Z'``` – Marthijn Bontekoning May 01 '18 at 21:13
  • 1
    Be aware that you disable the right to perform range queries if you do this. There's a reason why many databases store date as millisecond time format. – Oliver Dixon Dec 16 '18 at 22:25
  • 1
    @OliverDixon, Are you sure that range queries get disabled if we store time as ISO strings? I thought they are just strings, and have the right characteristics for sorting in the correct order if we treat them as strings. I've been sorting ISO date strings and assuming it was OK. Haven't tried database range queries on them but is there a limitation? – ProfDFrancis Dec 17 '18 at 00:37
  • Data(java.lang.String) is deprecated as of API 16. And it gives me an **FATAL EXCEPTION**: `java.lang.IllegalArgumentException at java.util.Date.parse(Date.java:638) at java.util.Date.(Date.java:274)` – Aliton Oliveira Jun 18 '19 at 20:08
  • One issue with doing this is comparing the current time for data that's come in with different timezones is complex. – Rob Grant Oct 31 '20 at 11:13
6

This is how I managed to store Date on Firebase by using the SimpleDateFormat to convert it to only a date without seconds, hours or milliseconds.

public void storeDatetoFirebase() {

    handler = new Handler();

    runnable = new Runnable() {
        @Override
        public void run() {
            handler.postDelayed(this, 1000);
            try {
                Date date = new Date();
                Date newDate = new Date(date.getTime() + (604800000L * 2) + (24 * 60 * 60));
                SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd");
                String stringdate = dt.format(newDate);

                System.out.println("Submission Date: " + stringdate);
                DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("My_Date");
                databaseReference.child("init_date").setValue(stringdate);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    handler.postDelayed(runnable, 1 * 1000);
}

and this is how it appears on Firebase:

Date onFirebase

Hope it helps..

Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132
Zack
  • 472
  • 7
  • 16
3

Although firebase does support Date format datatype, I would prefer to save date-time in a string format, because by storing it as a string it becomes quite easy to retrieve it.

To store current system date-time in a string format just below code will do.

        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();
        String strDate = dateFormat.format(date).toString();
        myRef.child("datetime").setValue(strDate);   

Now one can use the strDate to store in the firebase or do whatever one want to do with that string.

Nabajyoti Das
  • 454
  • 7
  • 10
  • Great plan! Even better to use ISO date format, so it will be even more painless to inter-operate with other systems etc. e.g. `2018-12-16T23:03:53Z` https://en.wikipedia.org/wiki/ISO_8601 – ProfDFrancis Dec 17 '18 at 00:39
-1

you can set a date object on Firebase

yourReference.setValue(new Date());

It works, But

I noticed other PROBLEM with the date, when i changed the month manually from the db, when retrieving it the value stays as before

RBT
  • 24,161
  • 21
  • 159
  • 240
yading
  • 9