So I have a Timestamp
in cloud firestore. I am using cloud function to retrieve data from firestore to flutter. But JSON
formats timestamp to map due to which I am not able to use it as timestamp. How to convert it again into timestamp?
This is how I ulpoaded timestamp to firestore.
var reference = Firestore.instance.collection('posts');
reference.add({
'postTitle': this.title,
'timestamp': DateTime.now(),
'likes': {},
'ownerId': userId,
})
To retrieve data this is the code:
factory Post.fromJSON(Map data){
return Post(
timestamp: data['timestamp'],
);
}
List<Post> _generateFeed(List<Map<String, dynamic>> feedData) {
List<Post> listOfPosts = [];
for (var postData in feedData) {
listOfPosts.add(Post.fromJSON(postData));
}
return listOfPosts;
}
but this returns an error.
I/flutter (17271): The following assertion was thrown building FutureBuilder<DocumentSnapshot>(dirty, state:
I/flutter (17271): _FutureBuilderState<DocumentSnapshot>#1536b):
I/flutter (17271): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Timestamp'
This is my cloud function.getFeed.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
export const getFeedModule = function(req, res){
const uid = String(req.query.uid);
async function compileFeedPost(){
const following = await getFollowing(uid, res)as any;
let listOfPosts = await getAllPosts(following, res);
listOfPosts = [].concat.apply([], listOfPosts);
res.send(listOfPosts);
}
compileFeedPost().then().catch();
}
async function getAllPosts(following, res) {
let listOfPosts = [];
for (let user in following){
listOfPosts.push( await getUserPosts(following[user], res));
}
return listOfPosts;
}
function getUserPosts(userId, res){
const posts = admin.firestore().collection("posts").where("ownerId", "==", userId).orderBy("timestamp")
return posts.get()
.then(function(querySnapshot){
let listOfPosts = [];
querySnapshot.forEach(function(doc){
listOfPosts.push(doc.data());
});
return listOfPosts;
})
}
function getFollowing(uid, res){
const doc = admin.firestore().doc(`user/${uid}`)
return doc.get().then(snapshot => {
const followings = snapshot.data().followings;
let following_list = [];
for (const following in followings){
if (followings[following] === true){
following_list.push(following);
}
}
return following_list;
}).catch(error => {
res.status(500).send(error)
})
}
cloud function index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import { getFeedModule } from "./getFeed"
admin.initializeApp();
export const getFeed = functions.https.onRequest((req, res) => {
getFeedModule(req, res);
})
invoked by this
_getFeed() async {
print("Starting getFeed");
FirebaseUser user = await FirebaseAuth.instance.currentUser();
SharedPreferences prefs = await SharedPreferences.getInstance();
String userId = user.uid;
var url =
'https://us-central1-jaluk-quiz.cloudfunctions.net/getFeed?uid=' + userId;
var httpClient = HttpClient();
List<QuizViewer>listOfPosts;
String result;
try {
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
String json = await response.transform(utf8.decoder).join();
prefs.setString("feed", json);
List<Map<String, dynamic>> data =
jsonDecode(json).cast<Map<String, dynamic>>();
listOfPosts = _generateFeed(data);
result = "Success in http request for feed";
} else {
result =
'Error getting a feed: Http status ${response.statusCode} | userId $userId';
}
} catch (exception) {
result = 'Failed invoking the getFeed function. Exception: $exception';
}
print(result);
setState(() {
feedData = listOfPosts;
});
}
firestore. Timestamp. A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time. It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one.
To convert a Firestore date or timestamp to a JavaScript Date, we use firebase. firestore. Timestamp. fromDate to convert the a date to a Firestore timestamp.
You can do this by comparing the seconds and nanoseconds properties on the Timestamp objects. Or, to make it simpler, and you don't need nanosecond precision, you can just compare the results of the results of their toMillis() values. This user is second on the weekly Google Cloud leaderboard.
If you are dealing with a Timestamp that's been serialized as an object with seconds and nanoseconds components, you can use those components to create a new Timestamp object with new Timestamp(seconds, nanoseconds)
.
Indeed, timestamps gets returned as plain Map when using Cloud functions. But if you use Firebase SDK it returns Timestamp
object.
I use the following function to handle both cases:
/// https://stackoverflow.com/a/57865272/1321917
DateTime dateTimeFromTimestamp(dynamic val) {
Timestamp timestamp;
if (val is Timestamp) {
timestamp = val;
} else if (val is Map) {
timestamp = Timestamp(val['_seconds'], val['_nanoseconds']);
}
if (timestamp != null) {
return timestamp.toDate();
} else {
print('Unable to parse Timestamp from $val');
return null;
}
}
Works perfectly with json_annotation
lib:
@JsonKey(
fromJson: dateTimeFromTimestamp,
toJson: dateTimeToTimestamp,
nullable: true)
final DateTime subscriptionExpiryDate;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With