如何在Firestore与JSON间导入导出时保留指定时间戳格式?
_seconds/_nanoseconds Objects) Got it, let's solve this problem. The firestore-export-import package outputs Firestore Timestamp fields as objects with _seconds and _nanoseconds by default, but we can modify your export script to convert Created_At and Updated_At into your desired format: Monday, 29 April 2019 15:07:59 GMT+05:30. We'll also cover how to reverse this process for importing back into Firestore.
Step 1: Modify the Export Script (export.js)
We'll add a custom function to format Timestamp objects into your target string, then process each document in the exported data before writing to the JSON file.
Here's the updated export.js with comments for the new code:
var express = require('express'); var router = express.Router(); var fs = require('fs'); var firestoreService = require('firestore-export-import'); var databaseURL = 'https://sample.firebaseio.com'; var serviceAccount = require('../sample.json'); // Initiate Firebase App firestoreService.initializeApp(serviceAccount, databaseURL); // Custom function to format Firestore Timestamp to your desired string function formatTimestamp(timestampObj) { // Skip if not a Timestamp object if (!timestampObj || !timestampObj._seconds) return timestampObj; // Convert seconds/nanoseconds to a Date object const date = new Date(timestampObj._seconds * 1000 + timestampObj._nanoseconds / 1000000); // Configure formatting options to match your desired output const formatOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'Asia/Kolkata' // Adjust this to your target timezone (GMT+05:30) }; // Generate initial formatted string let formattedDate = new Intl.DateTimeFormat('en-US', formatOptions).format(date); // Add GMT offset string (since Intl uses timezone names by default) const offsetMinutes = date.getTimezoneOffset(); const hours = Math.floor(Math.abs(offsetMinutes)/60); const minutes = Math.abs(offsetMinutes)%60; const offsetSign = offsetMinutes > 0 ? '-' : '+'; const gmtOffset = `GMT${offsetSign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`; // Replace timezone name with GMT offset in the final string formattedDate = formattedDate.replace(/\s\(.*\)$/, ` ${gmtOffset}`); return formattedDate; } router.get('/', async (req, res, next) => { firestoreService .backup('sample') // Collection/subcollection name .then(rawData => { // Process each document to convert timestamps const processedData = {}; Object.keys(rawData).forEach(docId => { const doc = rawData[docId]; // Convert Created_At if present if (doc.Created_At) { doc.Created_At = formatTimestamp(doc.Created_At); } // Convert Updated_At if present if (doc.Updated_At) { doc.Updated_At = formatTimestamp(doc.Updated_At); } processedData[docId] = doc; }); // Write processed data to JSON file fs.writeFile("sample.json", JSON.stringify(processedData), function (err) { if (err) { console.log("error:", err.message); res.json({ returncode: 201, message: err.message }) } else { console.log("Data Exported Successfully"); res.json({ returncode: 200, message: "Data Exported Successfully" }) } }); }) }); module.exports = router;
Step 2: Modify the Import Script (import.js)
If you need to import the formatted data back into Firestore, you'll need to convert the date strings back into Firestore Timestamp objects. Here's the updated import.js:
var express = require("express"); var router = express.Router(); const firestoreService = require("firestore-export-import"); var fs = require('fs'); var databaseURL = "https://sample.firebaseio.com"; var serviceAccount = require("../sample.json"); // Initiate Firebase App firestoreService.initializeApp(serviceAccount, databaseURL); router.get("/", async (req, res, next) => { // Read the JSON file first fs.readFile('./sample.json', 'utf8', (err, rawJson) => { if (err) { return res.json({ returncode: 201, message: err.message }); } const rawData = JSON.parse(rawJson); const processedData = {}; // Convert date strings back to Firestore Timestamps Object.keys(rawData).forEach(docId => { const doc = rawData[docId]; // Convert Created_At back to Timestamp if (doc.Created_At && typeof doc.Created_At === 'string') { const date = new Date(doc.Created_At); doc.Created_At = new firestoreService.firestore.Timestamp( Math.floor(date.getTime() / 1000), date.getMilliseconds() * 1000000 ); } // Convert Updated_At back to Timestamp if (doc.Updated_At && typeof doc.Updated_At === 'string') { const date = new Date(doc.Updated_At); doc.Updated_At = new firestoreService.firestore.Timestamp( Math.floor(date.getTime() / 1000), date.getMilliseconds() * 1000000 ); } processedData[docId] = doc; }); // Restore processed data to Firestore firestoreService .restore(processedData) // Pass processed data instead of file path .then(async function () { console.log("Data Imported Successfully"); return res.json({ returncode: 200, message: "Data Imported Successfully" }); }) .catch(function (err) { return res.json({ returncode: 201, message: err.message }); }); }); }); module.exports = router;
Key Notes
- Timezone Adjustment: In the
formatTimestampfunction, changetimeZone: 'Asia/Kolkata'to match your desired timezone (e.g.,'Europe/London'for GMT+00:00). - Handling Subcollections: If your collection has subcollections, you'll need to add recursion to the processing logic to handle nested documents (let me know if you need help with that!).
- Timestamp Validation: The functions include checks to skip non-Timestamp fields, so other data types won't be affected.
内容的提问来源于stack exchange,提问作者Vijay Rahul

