简体   繁体   中英

'Timestamp' is not a subtype of type 'int' - Flutter - Firebase Firestore

I got an error when I try to get Time set data from Cloud Firestore. I think if I set timestampsInSnapshots: true then the issue will be fixed, but I can't set it because I use cloud_firestore: ^0.16.0 so I couldn't found how can I do this. if I use cloud_firestore: ^0.8.2+1 then I can configure the Firestore's settings. But I wanna set this configuration in version 0.16.0

About Issue:

The following _TypeError was thrown building StreamBuilder<QuerySnapshot>(dirty, state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#ec8a0):
type 'Timestamp' is not a subtype of type 'int'

The relevant error-causing widget was
StreamBuilder<QuerySnapshot>
lib/…/main/profile.dart:66
When the exception was thrown, this was the stack
#0      _ProfileState.buildExamHistoryList.<anonymous closure>.<anonymous closure>
lib/…/main/profile.dart:97
#1      MappedListIterable.elementAt (dart:_internal/iterable.dart:411:31)
#2      ListIterator.moveNext (dart:_internal/iterable.dart:340:26)
#3      new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:188:27)
#4      new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
...

enter image description here

The stream where I wanna set my data from firestore:

Widget buildExamHistoryList() {
    return StreamBuilder<QuerySnapshot>(
      stream: usersRef.doc(widget.userID).collection('examResults').snapshots(),
      builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (snapshot.hasError) {
          return Center(
            child: Text("Something Went Wrong"),
          );
        }
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return Container(
              padding: EdgeInsets.only(top: 100),
              child: Center(
                child: SpinKitFadingCircle(
                  color: Colors.black,
                  size: 50,
                ),
              ),
            );
            break;
          default:
            return Column(
              children: [
                ListView(
                  shrinkWrap: true,
                  children: snapshot.data.docs.map((doc) {
                    return Padding(
                      padding: const EdgeInsets.all(10),
                      child: ExamHistoryCard(
                        correctAnswersCount: doc['correctAnswersCount'],
                        incorrectAnswersCount: doc['incorrectAnswersCount'],
                        date: _examHistoryService.readTimestamp(doc['date']),
                      ),
                    );
                  }).toList(),
                ),
              ],
            );
        }
      },
    );
  }

and that is my readTimestamp function:

 String readTimestamp(int timestamp) {
    var now = DateTime.now();
    var format = DateFormat('HH:mm a');
    var date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    var diff = now.difference(date);
    var time = '';

    if (diff.inSeconds <= 0 ||
        diff.inSeconds > 0 && diff.inMinutes == 0 ||
        diff.inMinutes > 0 && diff.inHours == 0 ||
        diff.inHours > 0 && diff.inDays == 0) {
      time = format.format(date);
    } else if (diff.inDays > 0 && diff.inDays < 7) {
      if (diff.inDays == 1) {
        time = diff.inDays.toString() + ' Dünen';
      } else {
        time = diff.inDays.toString() + ' Gün Önce';
      }
    } else {
      if (diff.inDays == 7) {
        time = (diff.inDays / 7).floor().toString() + ' Hefte Önce';
      } else {
        time = (diff.inDays / 7).floor().toString() + ' Hefte Önce';
      }
    }

    return time;
  }

The dates you get from firebase in doc['date'] is a Timestamp, not an int. You can transform it into a Date by using toDate() method or to milliseconds since epoch with toMillis() like this:

final Timestamp timestamp = doc['date'];
final DateTime date = timestamp.toDate();
final int millis = timestamp.toMillis()

Also be sure to declare the correct type you are going to be passing to your readTimestamp function:

String readTimestamp(Timestamp timestamp) {}

or

String readTimestamp(DateTime date) {}

or

String readTimestamp(int millis) {}

Try this

String readTimestamp(Timestamp timestamp) {
    var now = DateTime.now();
    var format = DateFormat('HH:mm a');
    var date = timestamp.toDate();
    var diff = now.difference(date);
    var time = '';

    if (diff.inSeconds <= 0 ||
        diff.inSeconds > 0 && diff.inMinutes == 0 ||
        diff.inMinutes > 0 && diff.inHours == 0 ||
        diff.inHours > 0 && diff.inDays == 0) {
      time = format.format(date);
    } else if (diff.inDays > 0 && diff.inDays < 7) {
      if (diff.inDays == 1) {
        time = diff.inDays.toString() + ' Dünen';
      } else {
        time = diff.inDays.toString() + ' Gün Önce';
      }
    } else {
      if (diff.inDays == 7) {
        time = (diff.inDays / 7).floor().toString() + ' Hefte Önce';
      } else {
        time = (diff.inDays / 7).floor().toString() + ' Hefte Önce';
      }
    }

    return time;
  }

Timestamp from Firebase will be formatted as Timestamp or Map .

Here DatetimeConverter taking care of the conversion from/to json from Firebase Firestore and Cloud Functions:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

class DatetimeConverter implements JsonConverter<DateTime, dynamic> {
  const DatetimeConverter();

  @override
  dynamic toJson(DateTime object) {
    return object != null
        ? Timestamp.fromDate(object)
        : FieldValue.serverTimestamp();
  }

  @override
  DateTime fromJson(dynamic val) {
    Timestamp timestamp;
    if (val is Timestamp) {
      // the firestore SDK formats the timestamp as a timestamp
      timestamp = val;
    } else if (val is Map) {
      // cloud functions formate the timestamp as a map
      timestamp = Timestamp(val['_seconds'] as int, val['_nanoseconds'] as int);
    }
    if (timestamp != null) {
      return timestamp.toDate();
    } else {
      // Timestamp probably not yet written server side
      return Timestamp.now().toDate();
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM