explain MongoDB date format - javascript

For defining a model in node.js I am using mongoose library and I want to store the date in that.
here is the schema:
availability: [
{
day: {
type: String,
},
startTime: {
type: Date,
},
endTime: {
type: Date,
},
},
]
I am passing the value from postman like below:
{
"parkingId":"62cfa09adb8bc68f045b4d65",
"day":"Monday",
"startTime":7,
"endTime": 22
}
But it is getting saved like this from 1970. I am aware that passing a time like this will calculate time from Unix epoch But I want to save today's date or date passed by merchant user for availability
day:Monday,
startTime: ISODate("1970-01-01T00:00:00.007+00:00"),
endTime: ISODate("1970-01-01T00:00:00.022+00:00")
And also what is 007+00:00 or 022+00:00?
Should I use moment library for that?

This is unrelated to MongoDB, this is a mongoose feature.
You define startTime and endTime as Date in your schema, but you are passing a number. let's see what the mongoose code does in this scenraio:
function castDate(value) {
...
let date;
if (value instanceof Number || typeof value === 'number') {
date = new Date(value);
}
...
};
As you can see in the case the input value is a number which is the case here, the mongoose schema casts this value to date using js new Date() function which is basically:
JavaScript Date objects represent a single moment in time in a platform-independent format. Date objects contain a Number that represents milliseconds since 1 January 1970 UTC.
This means when it casts new Date(7) the result is 1 January 1970 UTC + 7 mili seconds whichi is the 7 your seeing in the result 1970-01-01T00:00:00.007+00:00
Clearly in your case all you need to do is change the Date type to Number which is actually what you're trying to save.

Related

There is no calibration between MongoDB UTC time and local time

Data is stored and inquired through the API on the web page, and the API is using MongoDB.
The server space has been unified to UTC time so that the same results can be achieved in different time zones.
MongoDB uses the Mongoose schema as follows:
const userSchema = new Schema({
userId : {
type : String
},
score : {
type : Number
},
createdAt : {
type : Date,
default : Date.now
}
});
Because Date.now in the schema is in the createdAt field by default, it does not pass the Date value separately when querying the create or update of mongoose.
Considering the case where offset exists based on UTC time, the time is calculated using moment.js as follows:
// -540 offset value for KST 9 hours faster than UTC
const utc= moment.utc().add(offset, 'm').format('YYYY-MM-DDTHH:mm:ssZ');
let beginDate = new Date(utc);
let endDate = null;
let year = beginDate.getFullYear();
let month = beginDate.getMonth();
let date = beginDate.getDate();
// To view the full duration of the day
beginDate = new Date(new Date(year, month, date).setHours(0, 0, 0, 0));
endDate = new Date(new Date(year, month, date).setHours(23, 59, 59, 59));
// Find document
const user = await userSchema.aggregate([
{
$unwind : 'lists'
},
{
$match : {
'lists.createdAt' : {
$gte : beginDate,
$lte : endDate
}
}
},
...
]);
For example, if you make a query in Korea, the data inquiry may differ from the time after midnight and to 9 a.m. the next day.
What is wrong with the above parallax correction logic? I don't exactly understand the current problem.
Why so difficult? Simply use
{
$match : {
'lists.createdAt' : {
$gte : moment().startOf('day').toDate(),
$ltr : moment().endOf('day').toDate()
}
}
}
moment().startOf('day').toDate() returns the begin of current day in your local time zone. I live in Switzerland, thus it returns ISODate("2023-01-17T23:00:00.000Z")
But you can specify also a time zone, e.g.
moment.tz('Asia/Seoul').startOf('day').toDate();
ISODate("2023-01-17T15:00:00.000Z")
The problem is moment.utc().add(...) really modifies the time value. But that is not what you need to do, you like to change only the way how the time is displayed in your local time zone.
For comparison and calculations, the displayed value does not matter. All methods are done in UTC time only.

Why does react keep changing into an unecessary timezone I just want to create a date object with the same date in the string

I found another answer in stack overflow and it used the Date.UTC to create a normal date object without changing the original string date that was passed into it. I tried it in both the command line with the following code
let test_1 = new Date("2022-12-24T23:40:01Z");
const temp_date_1 = {
month: test_1.getMonth() + 1,
date: test_1.getUTCDate(),
year: test_1.getFullYear(),
hour: test_1.getUTCHours(),
minute: test_1.getUTCMinutes(),
second: test_1.getUTCSeconds(),
}
const utc_1 = new Date(Date.UTC(
temp_date_1.year,
temp_date_1.month - 1,
temp_date_1.date,
temp_date_1.hour,
temp_date_1.minute,
temp_date_1.second
));
console.log(utc_1);
but when I try it in react the date changes
const temp_deadline = new Date("2022-12-24T23:40:01Z");
const new_deadline = new Date(Date.UTC(
temp_deadline.getFullYear(),
temp_deadline.getMonth(),
temp_deadline.getUTCDate(),
temp_deadline.getUTCHours(),
temp_deadline.getUTCMinutes(),
temp_deadline.getUTCSeconds(),
))
//
console.log(new_deadline)
// this prints out Sun Dec 25 2022 07:40:01 GMT+0800 (Singapore Standard Time) which is wrong in the date wrong and wrong in the hour
Your code is behaving as expected.
Date objects store an unambiguous representation of a specific moment in time:
Note: It's important to keep in mind that while the time value at the heart of a Date object is UTC, the basic methods to fetch the date and time or its components all work in the local (i.e. host system) time zone and offset.
This should fully answer your question. Your date object is a pure, absolute date object even if the console prints it using your environment's timezone. You have plenty of date methods to handle your date as needed. Read the above linked documentation.
This is simply how JavaScript dates work. So there is nothing you can do to change this behavior.
Additionally:
A JavaScript date is fundamentally specified as the number of milliseconds that have elapsed since midnight on January 1, 1970, UTC.
So, a date can be stored losslessly by storing the number of milliseconds since midnight on January 1, 1970, UTC (Use Date.prototype.getTime()). Consequently, our code can be rewritten as:
const temp_deadline = new Date("2022-12-24T23:40:01Z");
const new_deadline = new Date(temp_deadline.getTime());
console.log(new_deadline);
temp_deadline and new_deadline above represent both the same exact date/instant in the same way.
Just remember:
A date can be absolutely and completely represented by the number of milliseconds since midnight on January 1, 1970, UTC.
A date object can be instantiated by using that number of milliseconds and will represent the exact date/instant all around the world, even if it is displayed in the local timezone.
There are date methods that will automatically convert the core UTC representation into a local timezone representation (the majority of date methods).
There are other special methods (UTC, ISO, GMT methods) that allow you to work with a "normalized" representation.
Date.prototype.getTime() is the absolutest and purest representation of a date in JavaScript.
It's still the same date & time, you're just viewing it in a different timezone, and since on that timezone it's after midnight, the date has changed as well.
You can define the timezone when printing it out. For instance:
const temp_deadline = new Date("2022-12-24T23:40:01Z");
console.log(temp_deadline.toLocaleString('en-US', { timeZone: 'Asia/Jakarta' }));
12/25/2022, 6:40:01 AM
console.log(temp_deadline.toLocaleString('en-US', { timeZone: 'Europe/Helsinki' }));
12/25/2022, 1:40:01 AM
console.log(temp_deadline.toLocaleString('en-US', { timeZone: 'America/Mexico_city' }));
12/24/2022, 5:40:01 PM
Probably the react code stringifies the date value. In that case the date is automatically converted to a datetime in the current (local) time zone. So, for printing the date value from a Date Object without any time zone misery, it's best to format it yourself.
const dl = new Date("2022-12-24T23:40:01Z");
const log = (...strs) =>
strs.forEach(str => document.querySelector("pre").textContent += str + `\n`);
const pad = (nr, n = 2) => `${nr}`.padStart(n, `0`);
const justDisplayTheDamnedDateValueLikeIWantItTo = dl =>
`${dl.getFullYear()}-${pad(dl.getUTCMonth()+1)}-${
pad(dl.getUTCDate())}T${pad(dl.getUTCHours())}:${pad(dl.getUTCMinutes())}:${
pad(dl.getUTCSeconds())}:${pad(dl.getUTCMilliseconds(), 3)}Z`;
log(`Is 'dl' an instance of Date (a 'Date Object')? ${
dl.constructor === Date ? `yep`: `nope`}`, ``,
`"when I print" is the keyword here.`,
`Printing means: display something as a *string* (stringify).`,
`If you don't want the browser to apply its own rules, `,
`you have format the Date Object yourself.`, ``,
`So let's run 'justDisplayTheDamnedDateValueLikeIWantItTo(dl)': ${
justDisplayTheDamnedDateValueLikeIWantItTo(dl)}`);
body {
font: normal 12px/15px verdana, arial, sans-serif;
margin: 2rem;
}
blockquote {
color: #c0c0c0;
padding-left: 15px;
margin-left: 0;
}
blockquote:before {
content: "> ";
font-size: 1.2rem;
margin-left: -20px;
}
<blockquote>I just want the new-deadline to be a datetime object that's all</blockquote>
<p>And that's what it is</p>
<blockquote>I don't want it to be a string, I want it to log 2022-12-24T23:40:01.000Z when I print the object so I know the object is purely this date and not a freakin time zone like singapore and some country from who gives a damn</blockquote>
<pre></pre>

Create a document and set the date - Mongoose

I'm trying to create a document in mongo with a field date: Date.
When I post to API, the document created has a different time that I set, as follows:
{
"serialnumber": "1234567",
"date": "2019-08-30T10:32"
}
Result:
{
"troubles": [],
"_id": "5c35e9c8e726822a243936a9",
"serialnumber": "1234567",
"date": "2019-08-30T13:32:00.000Z",
"updated": "2019-01-09T12:32:08.996Z",
"__v": 0
}
My mongoose Schema:
var MeasurementSchema = new Schema({
serialnumber: String,
date: Date
......
As we saw, I wrote 'T10:32', but, the time of parameter 'date' results in 12:32.
Any tips?
MongoDB stores times in UTC by default, and will convert any local time representations into this form.
Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.
Example
In the MongoDB shell, you can store both the current date and the current client’s offset from UTC.
var now = new Date();
db.data.save( { date: now,
offset: now.getTimezoneOffset() } );
You can reconstruct the original local time by applying the saved offset:
var record = db.data.findOne();
var localNow = new Date( record.date.getTime() - ( record.offset * 60000 ) );

Saving a String in MongoDB as a date saves wrong values

I am trying to save a string in MongoDB as a date but having hard times for storing the right values.
In Mongoose schema data value is stored as Date, however, I pass the value to data as new Date("MM-dd-YYYY") but when I look up in the database the value is transformed to this format ISODate("YYYY-MM-dd-1T21:00:00Z")
The format wouldn't bother me if the date would be the same but as you notice the value in the database is one day earlier then the value which I want to be.
So instead of 2018-09-20 is 2018-08-19. My guess is that default UTC time is not the same or something like that but how can I set the correct UTC time?
Edit:
var mongoose = require('mongoose')
var dateformat =require('moment');
//Schema
var ReservationSchema = mongoose.Schema({
name : {
type:String,
required : true,
},
numberOfGuests : {
type : Number ,
required : true,}
,
email: {
type : String,
required:true,
},
phone: {
type : String,
required:true,
},
data:{
type:Date,
require:true,
},
timetables:{
type:String,
require:true,
},
furtherRequests: {
type : String,
}
});
var reservvar = module.exports = mongoose.model('Rezervari', ReservationSchema ,'Rezervari');
module.exports.createReservation = function (query,callback){
//query.data = dateformat.utc(query.data).format("MM-DD-YYYY")
reservvar.create(query,callback);
}
module.exports.getReservations = function (callback){
reservvar.find({},callback);
}
Index.js file :
app.get('/api/reservations',function(req,res) {
Rezervari.getReservations(function(err,reserv){
if(err){
throw err;
}
var changetime = reserv[1].data;
console.log(reserv[1].data)
changetime = dateformat.utc(changetime).format("MM-DD-YYYY") // this one returns the date in desired format but with wrong values as stored in db
console.log(changetime)
res.json(reserv);
});
});
app.post('/api/createrezervare', function (req,res) {
const reserv = req.body
const name = reserv.name
const numberofg = reserv.number
const phone = reserv.phone
const email = reserv.email
const data = reserv.date
const timetable = reserv.time
const furtreq = reserv.frequests
Rezervari.createReservation({name:name,numberOfGuests:numberofg,phone:phone,email:email,data:data,timetables:timetable,furtRequests:furtreq},function(err,reserv){
if(err){
throw err}
res.json({status:true})
})
})
You are inserting a Javascript Date Object from Node.js, and that same Date is being inserted in MongoDB, it's being inserted correctly.
I think you are confusing how dates are stored internally and how are they formatted when you print them.
When you check the content of your data in MongoDB it's just shown in that particular format, an ISO date. If you take a close look at the date shown you can see a Z a the end, Z means "zero hour offset" also known as "Zulu time" (UTC).
In Javascript when you create a Date object without setting the timezone, it's by default created in your system timezone. Also, Date objects are not stored with any format, nor in JS nor in MongoDB. In JS, dates are stored internally as time values (milliseconds since 1970-01-01).
Supposing we are in Japan, JST time (UTC+9):
const d = new Date("09-20-2018");
console.log(d.getTime()); // 1537369200000
console.log(d.toString()); // Thu Sep 20 2018 00:00:00 GMT+0900 (JST)
console.log(d.toISOString()); // 2018-09-19T15:00:00.000Z
First we are printing out the number of ms, after the Date including the timezone, and finally the ISO Date, almost same format that MongoDB uses to print dates in the Mongo shell (anyway, in UTC).
So, new Date("09-20-2018") is going to store the milliseconds until 09-20-2018 00:00 in Japan Time. Then, if you insert that object in MongoDB, internally it will store the correct date (I don't know internal details of MongoDB, but maybe it's storing the milliseconds as well).
If you check MongoDB you will see something like ISODate("2018-09-19T15:00:00Z").

How do I convert a Firestore date/Timestamp to a JS Date()?

I am trying to convert the below date to a javascript Date() object. When I get it back from the server, it is a Timestamp object,
Screenshot from Firebase Firestore console:
When I try the following on a list of objects returned from firestore:
list.forEach(a => {
var d = a.record.dateCreated;
console.log(d, new Date(d), Date(d))
})
I get this output:
Clearly the Timestamps are all different, and are not all the same date of Sept 09, 2018 (which happens to be today). I'm also not sure why new Date(Timestamp) results in an invalid date. I'm a bit of a JS newbie, am I doing something wrong with the dates or timestamps?
The constructor for a JavaScript's Date doesn't know anything about Firestore's Timestamp objects — it doesn't know what to do with them.
If you want to convert a Timestamp to a Date, use the toDate() method on the Timestamp.
You can use toDate() function along with toDateString() to display the date part alone.
const date = dateCreated.toDate().toDateString()
//Example: Friday Nov 27 2017
Suppose you want only the time part then use the toLocaleTimeString()
const time = dateCreated.toDate().toLocaleTimeString('en-US')
//Example: 01:10:18 AM, the locale part 'en-US' is optional
You can use Timestamp.fromDate and .toDate for converting back and forth.
// Date to Timestamp
const t = firebase.firestore.Timestamp.fromDate(new Date());
// Timestamp to Date
const d = t.toDate();
How to convert Unix timestamp to JavaScript Date object.
var myDate = a.record.dateCreated;
new Date(myDate._seconds * 1000); // access the '_seconds' attribute within the timestamp object
Please use toDate() method and then convert it into the format using angular pipe like this -
{{ row.orderDate.toDate() | date: 'dd MMM hh:mm' }}
apart from other answers you can do it like this as well
//date from firebase is represented as
let time = {
seconds: 1613748319,
nanoseconds: 47688698687,
}
const fireBaseTime = new Date(
time.seconds * 1000 + time.nanoseconds / 1000000,
);
const date = fireBaseTime.toDateString();
const atTime = fireBaseTime.toLocaleTimeString();
console.log(date, atTime);
At last, I could get what I need. This returns date as 08/04/2020
new Date(firebase.firestore.Timestamp.now().seconds*1000).toLocaleDateString()
const timeStampDate = record.createdAt;
const dateInMillis = timeStampDate._seconds * 1000
var date = new Date(dateInMillis).toDateString() + ' at ' + new Date(dateInMillis).toLocaleTimeString()
OutPut Example: Sat 11 Jul 2020 at 21:21:10
This might help:
new Date(firebaseDate._seconds * 1000).toUTCString()
A simple way is to convert firestore timestamp to epoch timestamp is by using toMillis() method on firestore timestamp.
For example:
You have a firestore timestamp
created_on : Timestamp { _seconds: 1622885490, _nanoseconds: 374000000 }
let epochTimestamp = created_on.toMillis()
//epochTimestamp = 1621081015081
//Now this timestamp can be used as usual javascript timestamp which is easy to manipulate.
let date = new Date(epochTimestamp) //date = Sat May 15 2021 17:46:55 GMT+0530 (India Standard Time)
The timestamp object you get from firestore has a toDate() method you can use.
list.forEach(a => {
var d = a.record.dateCreated;
console.log(d.toDate())
})
Here's a quote from firebase docs about the toDate() method
Convert a Timestamp to a JavaScript Date object. This conversion
causes a loss of precision since Date objects only support millisecond
precision.
Returns Date JavaScript Date object representing the same point in
time as this Timestamp, with millisecond precision.
https://firebase.google.com/docs/reference/js/firebase.firestore.Timestamp#todate
This works for me.
new Date(firebaseDate.toDate())
This works for me
let val = firebase.timestamp // as received from the database, the timestamp always comes in an object similar to this - {_nanoseconds: 488484, _seconds: 1635367}
(new Date( (val.time._seconds + val.time._nanoseconds * 10 ** -9) * 1000)).toString().substring(17, 21)
Lots of answer here, but as a rookie I found most of them confusing.
So for rookies like me, here is a simple explanation of how to convert a Firestore date/Timestamp to a Javascript Date() and why you need to.
Why convert?
Firestore stores Dates as a Timestamp object. This is not the same as a Javascript Date() object.
This was confusing to me because if you send a Date() object to Firestore, and then retrieve it, it will hand you back a Timestamp object. Like if you hand Firestore a dollar, it will hand you back 4 quarters. It is the same amount of money (or same date), but if you were expecting paper, and got metal, you would be confused.
How to convert
Luckily the Timestamp object has functions built into do give you a Javascript Date object: toDate
Note: Remember, toDate looks like the Javascript toLocaleDateString() or toDateString() but it is not. A JS Date() object and Firestore Timestamp object are not the same so don't make my rookie mistake of trying to use functions from one, on the other.
To convert a Firestore Timestamp into a Javascript date, just call .toDate() on the Timestamp.
//get the document from Firestore
let fireStoreTimestamp = doc.data().nameOfYourDateField;
let javascriptDate = fireStoreTimestamp.toDate();
You can use the dayjs library to convert firebase firestore timestamp seconds to your local time.
newDate = dayjs.unix(date.seconds).$d;
It will take
date: {
seconds: 1639506600,
nanoseconds: 0
}
and convert it to
Date Sat Nov 16 2019 00:00:00 GMT+0530 (India Standard Time)
To help those still looking around for an answer to convert Firestore Date to JS Date to display in the web app. Here goes an example using typescript...
import {
Timestamp,
} from "firebase/firestore";
interface IStuff {
createdAt: Timestamp;
}
const insertStuff = async (text: string) => {
await addDoc(collection(db, "coolstuff"), {
text,
createdAt: serverTimestamp(),
});
};
<p>{item.createdAt?.toDate().toDateString()}</p>
// OR
<p>{item.createdAt?.toDate().toLocaleTimeString()}</p>
Extending Waleed Tariq answer, to get a more readable string:
function formatDate(date) {
const formatDate = new Date(
date.seconds * 1000 + date.nanoseconds / 1000000
);
return formatDate.toLocaleTimeString('en-us', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
}
const timeStamp = {nanoseconds: 184000000, seconds: 1664826910};
console.log(formatDate(timeStamp))
I had the same problem. And i figured out like this:
const createdAt = firebase.firestore.Timestamp.fromDate(new Date());
// then using dayjs library you can display your date as you want.
const formatDate = dayjs.unix(createdAt.seconds).format('YYYY-MM-DD');
Output should look like e.g. 2020-08-04
If you want don't want to lose the milliseconds you can do the following:
var myDate = a.record.dateCreated;
new Date((myDate.seconds + myDate.nanoseconds * 10 ** -9) * 1000);
i work in angular.
i have an interface and a field date: Date.
the angular pipe date no work: order.date | date:'medium'
i change type of field date in interface
date: firebase.firestore.Timestamp
the angular pipe date work, but with function toDate()
order.date.toDate() | date:'medium'
It's very simple really. Use this simple epoch converter function which converts epoch seconds into Javascript date and time.
function getUNIXTime(dt) {
let unix = new Date(dt * 1000);
return unix.toUTCString().slice(5, 16);
}
Pass the timestamp.seconds into this function then slice it according to your needs to get a string of text with date and time.
Normally using any type (i.e. loginDate:any) and toDate() worked without problem in my all projects. But in my last project it didn't. I saw seconds in Timestamp object is _seconds anymore (Firebase 8.6.8). This type of change may have affected it. I don't know but i had no time so i used an alternative solution. A custom pipe. It can be used as an alternative:
import { Pipe, PipeTransform } from '#angular/core';
import { formatDate } from '#angular/common';
#Pipe({
name: 'timestamp'
})
export class TimestampPipe implements PipeTransform {
transform(value: any, format?: string) {
if (!value) { return ''; }
if (!format) { format = 'dd MMM yy'; }
return formatDate(value._seconds * 1000, format, 'tr');
}
}
and
{{ item.endDate | timestamp}}
P.S. Type is not important with this pipe. Worked with loginDate:any or loginDate:Date well.
to store timestamp into firestore:
import * as firebaseAdmin from "firebase-admin";
const created = firebaseAdmin.firestore.FieldValue.serverTimestamp();
// type
created: FirebaseFirestore.Timestamp | FirebaseFirestore.FieldValue | undefined;
To read back as a js Date object
const createDate = (created as FirebaseFirestore.Timestamp).toDate();
To read back as RFC3339 string
const createDate = (created as FirebaseFirestore.Timestamp).toDate().toISOString();
Web Firestore Timestamp:
function dateToFirestoreTimestamp(dateString = ''){
var timestampDate = new Date(); // this will return current date-time
if(dateString != ''){
// this will return timestamp according to provided date-time
dateString = dateString.replace(' ', 'T');
timestampDate = new Date(dateString);
}
timestampDate = firebase.firestore.Timestamp.fromDate(timestampDate);
return timestampDate;
}
This is by far the most elegant, precise and easiest way to convert a firebase-timestamp to a date (no dependenceis etc. needed)
const date = new Intl.DateTimeFormat(
'de-De', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
}
).format(firebaseTimeStamp.toDate())
Here is a cheatsheet with all necesarry parameters
this is the different thing between firestore timestamp and Javascript Date() object. if you want to use javascript Date() object from firestore timestamp, this is what I do:
const foo = new Date(firestoreTimestamp.toDate());
then you can use the javascript Date() object, as usual. here are some references:
https://www.w3schools.com/jsref/jsref_obj_date.asp
For example, we want to retrieve the date from the Date() object with string format:
const foo = new Date(firestoreTimestamp.toDate());
foo.toLocaleDateString();
etc.

Categories