Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to map to FIRTimestamp #36

Open
cerupcat opened this issue Apr 21, 2018 · 30 comments
Open

How to map to FIRTimestamp #36

cerupcat opened this issue Apr 21, 2018 · 30 comments

Comments

@cerupcat
Copy link

I'm trying to figure out how map to FIRTimestamp since it's not codable currently. Is there a way to transform the data returned from FIRTimestamp to Date instead or make FIRTimestamp codable so that it maps correctly?

@dannypier
Copy link

Struggling with this as well as Firestore has now made the push to FIRTimestamp and .dateValue. Would be happy to do a PR for the feature if I could get a little guidance.

@dannypier
Copy link

@cerupcat I would not use this in production, but here's a hack I was able to get FIRTimestamps working with. Again... it's a HACK, be forewarned.

#42

@cerupcat
Copy link
Author

cerupcat commented May 9, 2018

Thanks, i'll take a look.

@alickbass
Copy link
Owner

Hey guys! First of all, sorry for being unresponsive lately... I am really glad that there is support from community!

About the issue. I think that the proper way to do it, would be to do something similar to here. So we can make FirTimestamp Encodable and it will be skipped and left untouched when encoding and thus will let the Firestore handle it. I will open a PR with an example of how to use it! What do you think about it?

@jonandersen
Copy link

@alickbass would be great if we get some best practice guidance on that!

@alickbass
Copy link
Owner

alickbass commented May 19, 2018

Hey guys! The PR makes Timestamp conform to Codable and you can use it directly in your code just like normal Date. Something like below:

import CodableFirebase

extension Timestamp: TimestampType {}

struct FirTimestampModel: Codable {
  let timestamp: Timestamp
}

let timestamp = FirTimestampModel(timestamp: Timestamp(date: Date()))
let data = try! FirestoreEncoder().encode(timestamp)

If you want to use Date in your models and convert to Timestamp on server, I would really discourage that, as then you will lose all the precision.

@luca251117
Copy link

Thank you for your effort 👍

@dannypier
Copy link

Thanks @alickbass! Agree to disagree about having Timestamp in your models though. Creating a dependency on Firestore for the Timestamp type at the model layer doesn't feel good to me.

@alickbass
Copy link
Owner

alickbass commented May 19, 2018

Well, I think that the reason to use FirTimestamp in the first place is that you are not satisfied with the precision of the Date. Why not use Date directly then?

@dannypier
Copy link

dannypier commented May 19, 2018

Yeah, I would prefer to use Date directly but a recent version of Firestore told (via a console message) that the using of Date was going to be deprecated and the correct thing to do was get dateValue of FIRTimestamp. That's actually the thing that got me involved in this issue, precision wasn't so much of a concern.

The behavior for system Date objects stored in Firestore is going to change AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to add the following code to your app before calling any other Cloud Firestore methods:

let db = Firestore.firestore()
let settings = db.settings
settings.areTimestampsInSnapshotsEnabled = true
db.settings = settings

With this change, timestamps stored in Cloud Firestore will be read back as Firebase Timestamp objects instead of as system Date objects. So you will also need to update code expecting a Date to instead expect a Timestamp. For example:

// old:
let date: Date = documentSnapshot.get("created_at") as! Date
// new:
let timestamp: Timestamp = documentSnapshot.get("created_at") as! Timestamp
let date: Date = timestamp.dateValue()

Please audit all existing usages of Date when you enable the new behavior. In a future release, the behavior will be changed to the new behavior, so if you do not follow these steps, YOUR APP MAY BREAK.

@alickbass
Copy link
Owner

Valid point, @dannypier... Maybe I will find a better alternative... I will keep you updated, guys

@serjooo
Copy link
Collaborator

serjooo commented Aug 23, 2018

@alickbass Right now Firestore is crashing while using Date objects in the model, and I am also not very keen to be using FIRTimestamp in my model objects. It's not a dependency I'd like to have in my project as we might shift from Firestore in the future.

Edit:
Firestore wasn't crashing because of the FIRTimestamp. Sorry, had a wrong call because of another Google product.

I took an attempt at supporting this. I realized the best way to do it is while encoding a Date object to convert it into FIRTimestamp with their initializer + (instancetype)timestampWithDate:(NSDate *)date; and while decoding if expecting a Date object taking the FIRTimestamp and doing timestamp.dateValue() and if expecting it as FIRTimestamp just return that

However, to achieve this CodableFirebase has to have access to FIRTimestamp in the project, that would mean we would need to add the Firestore pod into the project. I'm not sure how open you are to doing this.

@alickbass
Copy link
Owner

In general, I am okay with adding Firebase as a dependency and removing all the redundant protocols and just working with Firebase / Firestore values. If you guys are willing to contribute, please submit a PR and I would love to review. Unfortunately, I haven't had time lately to submit any code myself

@serjooo
Copy link
Collaborator

serjooo commented Sep 18, 2018

@alickbass I'll work on it this weekend. I was busy this past week. I'm going to try to do it without actually including Firebase as a dependency, if I am not able I'll just go ahead and add it.

@alickbass
Copy link
Owner

@serjooo tbh, I would like to add it as a dependency and remove all the weird protocols that we have.

@serjooo
Copy link
Collaborator

serjooo commented Sep 20, 2018

@alickbass What method do you see best fitting to add Firebase as a dependency? I stumbled upon this issue where things become a little tricky to add Firebase through Cocoapods

@jimijon
Copy link

jimijon commented Feb 19, 2019

Was this ever solved? @serjooo @alickbass

@serjooo
Copy link
Collaborator

serjooo commented Feb 19, 2019

@jimijon not yet. We need to add Firebase as a dependency of this project; however, I really had some hard time doing it and never had the time to research and give a shot again, but most probably I'll try to contribute again as I'm thinking of using CodableFirebase again for a future project of mine.

@siyao1030
Copy link

@serjooo @alickbass any updates on this and/or is there any workaround?
I had to update Firestore so I can use their new collection group query but keep running into the crash when decoding Date in the new version (Firebase 6.0.0, Firestore 1.3.0).

@serjooo
Copy link
Collaborator

serjooo commented May 30, 2019

@alickbass I finally found sometime to work on this today and I included the FirebaseFirestore pod as a dependency to CodableFirebase and started working on the Encoding and Decoding. However, I realized Google are almost ready to merge in your implementation and some changes on to master via this PR firebase/firebase-ios-sdk#2229

Do you think its still worth investing more time and doing the same implementation as that PR on CodableFirebase and merge it until they release?

Also something to note adding FirebaseFirestore stops support for macOS watchOS and tvOS because the Podspec lint errored as FirebaseFirestore itself doesn't have official support for them

@alickbass
Copy link
Owner

I have started working on that PR myself quite some time ago, however, due to change in work could not continue... I am not sure what is their roadmap and timeline is...

@serjooo
Copy link
Collaborator

serjooo commented May 31, 2019

Yes you are right it seems like they keep postponing the release and you can never be sure of what their timeline is. How about you submit a PR of your current work on a separate branch and we can work on it together?

@alickbass
Copy link
Owner

sorry, I meant the PR on Firebase itself 😂I haven't done anything here yet, so feel free to submit your ideas 😎

@SidPatel12
Copy link

let date: Date = timestamp.dateValue()

perfect one . it's woking for me. thank you so much for sharing

@danismatiazGL
Copy link

So, what happened with this ? I'm still dealing with

Expected to decode Date but found FIRTimestamp instead.

What do you guys suggest to solve this ? I have a Date object in my model

@SidPatel12
Copy link

So, what happened with this ? I'm still dealing with

Expected to decode Date but found FIRTimestamp instead.

What do you guys suggest to solve this ? I have a Date object in my model
}
**

let timestamp: Timestamp = dicDocument["Date"] as! Timestamp
let timeStmp = timestamp.dateValue()
msg.date = timeStmp

**
i have taken date variable and its type is Date() in model. i have stored date as timeStamp in firestore.

@serjooo
Copy link
Collaborator

serjooo commented Aug 19, 2019

@alickbass seems like Google merged Codable support into master firebase/firebase-ios-sdk#3198 didn't check the implementation or test it out myself. Will do that and close this issue accordingly

@Rspoon3
Copy link

Rspoon3 commented Jan 24, 2020

So, what happened with this ? I'm still dealing with
Expected to decode Date but found FIRTimestamp instead.
What do you guys suggest to solve this ? I have a Date object in my model
}
**

let timestamp: Timestamp = dicDocument["Date"] as! Timestamp
let timeStmp = timestamp.dateValue()
msg.date = timeStmp

**
i have taken date variable and its type is Date() in model. i have stored date as timeStamp in firestore.

How did you end up doing this?

@Rspoon3
Copy link

Rspoon3 commented Jan 24, 2020

@alickbass seems like Google merged Codable support into master firebase/firebase-ios-sdk#3198 didn't check the implementation or test it out myself. Will do that and close this issue accordingly

How does it compare to this library?

@bryan1anderson
Copy link

bryan1anderson commented Apr 1, 2021

I'm running into this
On my model I have these values:

    var created: Date?
    var updated: Date?

Firestore is returning them in this format: "updated": <FIRTimestamp: seconds=1617128658 nanoseconds=859000000>

My understanding is that I could use this library to decode from Timestamp directly to date like this:

let model = try FirestoreDecoder().decode(Model.self, from: item.data())

Unfortunately it throws the error: typeMismatch(Foundation.Date, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "created", intValue: nil)], debugDescription: "Expected to decode Date but found FIRTimestamp instead.", underlyingError: nil))

Does anyone know how to solve this? I'm pulling my hair out trying to avoid writing a custom initializer or even a custom model for the one area of the app where this model gets loaded up from the Firestore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests