Mongodb faulty date [duplicate] - mongodb

When I get the date object and print it in mongo shell, it display two different time as follows:
>new Date()
Mon Feb 06 2012 18:49:40 GMT+0530 (IST)
>printjson({created_at: new Date()})
{ created_at : ISODate("2012-02-06T13:19:40.313Z") }
The two times are different, what i am wrong.

This is because of mongodb always store dates in UTC format, but javascript show your local time. And printjson internal mongodb shell function that convert date from your local timezone to utc format. So it shows -5.30 hours backward from your current time.

The times are not different, they are exactly the same! It's merely the same time expressed in different timezones. The "Z" in ISODate means "UTC" (or as some people try to call it: GMT). You're on IST (Indian Standard Time I guess) which is at GMT+0530. 18:49:40 # GMT+5:30 is exactly the same as 13:19 # GMT.
When I run the same code you shown on the shell, I get:
> new Date()
ISODate("2012-02-06T13:34:10.667Z")
As you can see, that is also with "Z". Perhaps you're running an older version of the shell?
cheers,
Derick

Related

How can I update a date property in a MongoDb collection to drop the timezone and make it UTC using a script

I'm looking for a small script to update existing dates in a mongo database and change them to UTC without changing the dates. I had been adding documents into a MongoDb collection with some timeless date properties that, without intending it, included the local timezone. Now that I've caught my mistake, I'm setting their timezone to UTC in the client before being submitted: but, I want to fix the documents I added earlier. Would you provide a sample update script that magically fixes the currents dates I have entered: the properties in UTC should not be affected; the ones with EST or EDT timezones should become UTC dates without changing their dates.
Well, first thing is that Mongo dates are UTC, but still there were hours on the dates. To remove the dates, I did this:
db.coll.find({$where: "this.dt && this.dt.getUTCHours() > 0"}
).forEach(function(doc) {
db.coll.update({ _id : doc._id },
{ $set : { dt : new Date(doc.dt.getTime() -
(doc.dt.getUTCHours() * 60 * 60 * 1000))}});}
);
And this is a slightly modified copy of this:
https://stackoverflow.com/a/18773804/507421

Why do MongoDB ISODate and Date behave differently for getDay()?

Try this in a Mongo 2.6.4 shell:
> tues = ISODate("2014-07-01")
ISODate("2014-07-01T00:00:00Z")
> tues.getDay()
1
> tues = new Date(2014, 6, 1)
ISODate("2014-07-01T04:00:00Z")
> tues.getDay()
2
i.e. create an ISODate for July 1, 2014 (a Tuesday), and run getDay() to get the day of the week and get 1, then create the same date with a standard Javascript Date and, as expected with Javascript, getDay() returns 2.
From the Mongo docs, it seems ISODate is simply a wrapper for Date. I can't find any documentation saying it behaves differently for getDay(). Is this intended behavior? If so, why? A bug?
getDay is giving you the day based on the local timezone. I am suspecting you are in U.S. EDT timezone. So in the first case, your local time is still 2014-06-30 20:00:00 EDT (Mon).

Mongodb date is off by 1 hour

I am running mongodb on ubuntu server. The server time is
root# date
Thu Sep 13 21:15:58 BST 2012
But when I run the following command I get a different result
root# mongo
MongoDB shell version: 2.2.0
connecting to: test
> new Date()
ISODate("2012-09-13T20:15:58.670Z")
There is exactly one hour difference. When I update a documents updated_on field with php using MongoDate(), the value of the field is still 1 hour off.
[EDIT]
Actually I just checked my php error log and the time in the log file is 1 hour off as well
[13-Sep-2012 20:11:14 UTC] Log Message (Time should be 21:11:14)
Mongo tells you
2012-09-13T20:15:58.670Z
Z = Zulu time / Zero offset / UTC. You can also express the time in that TZ as 2012-09-13T20:15:58.670+00:00, as defined in the ISO8601 standard by the way.
BST is UTC+1. So, they are the same time but in different time zones.
You can resolve this issue by displaying the DateTime with ToLocalTime method.
MVC C# Example: #Model.StartDate.ToLocalTime()
This is due to the way MongoDB store datetime in BST format. So the daylight savings time or the time zone of the server will have an effect on the actual date time returned to the application. This simple code will be able to format as usual with ToString("dd MMMM yyyy hh:mm tt") or any other format based on your requirements.
Here you need to understand a concept in time setting in clocks called daylight saving time. In some countries around the world the clock is advanced by 1 or more hours to experience day light by one more hour. The difference between IST and GST is 5.30 hrs but the actual time difference is between New Delhi and London time is 6.30 hrs. See this article from 4GuysFromRolla for setting and using server time.
On windows change your timezone.
Controll Panel -> Date and Time -> Change on timezone -> (UTC) Coordinated universal time.
And then just change your time

PostgreSQL 9.1 timezones

I'm using postgresql to store some dates on a database.
In my application it is fundamental that it is completely aware of timezones and I was conducting some basic tests, between, client, server and database.
I'm sending the dates from a browser's application I did in GWT and read the dates on postgresql.
My tests:
The client is always in GMT Timezone, and I'm sending always the same date for each case.
13/04/2012 00:00:00 GMT+00
On posgres I'm changing timezones for each test. Between tests I'm removing all dates from the table.
To change the timezone on the posgres, I do it on the {PostgreSQL HOME}\9.1\data\postgresql.conf setting the timezene to the one I want.
Tests:
Client: 13/04/2012 00:00:00 GMT+00
1st test - posgres EST - 12/04/2012 19:00:00-05
According to postgresql documentation EST = GMT - 5
2nd test - posgres GMT + 5 - 12/04/2012 19:00:00-05
3rd test - posgres GMT - 5 - 13/04/2012 05:00:00+05
Now my question rises: According the the docs, EST = GMT - 5. So why am I reading it the other way around?
Am I missing something here?
EDIT
Technical aspects of my tests:
On the client I send this: 2012 Apr 13 00:00:00 GMT+00.
On the server I'm using JDBC to write on the db: convert java.utils.date to
java.sql.timestamp
java.sql.Timestamp sqlTimeStamp = new java.sql.Timestamp(date.getTime());
(date is java.utils.Date that comes from the client)
set the prepared statement
PreparedStatement ps = con.prepareStatement("INSERT INTO teste.dates (dates_tz, dates_ntz) VALUES (?, ?);"
ps.setTimestamp(1, sqlTimeStamp); ...
For the record, this is just something I want to understand, because overall it works well for my purposes..
Consider that warning in the documentation:
Another issue to keep in mind is that in POSIX time zone names,
positive offsets are used for locations west of Greenwich. Everywhere
else, PostgreSQL follows the ISO-8601 convention that positive
timezone offsets are east of Greenwich.
It looks like the opposite signs towards GMT you're seeing is exactly the effect of that divergence.
The timezone specified in postgresql.conf is probably interpreted with POSIX rules, but it's later displayed by SQL with ISO-8601 rules (the one that anyone really uses).
When the clock on the wall shows 2012-04-13 00:00 in a time zone '+5', the time in London (GMT or UTC) is 2012-04-12 19:00.
If you live in the USA, your local time zone may be '-5'. When it's midnight there, it is 05:00 in the morning in London.
That's just how it is. This detailed answer about handling of time zones in PostgreSQL may help you understand.

Convert timestamps stored in a Mongo collection

I have various timestamps stored in Mongo collections, some as floats and some as ints.
They are all stored in BST and the server will be switched to UTC soon. How do I convert them within Mongo to be UTC timestamps?
In MySQL I can do this:
UPDATE `table` SET `field` = CONVERT_TZ(`field`, 'Europe/London', 'UTC');
Is there a Mongo equivalent?
You'll have to use your language of choice and update them one at a time. It should be as simple as a for loop that loads the data and rewrites it.
Just double-check how your language of choice handles timestamps across timezones. Making such a data change can have all kinds of unexpected effects on production code.
Timestamps are generally in UTC and not in a specific timezone. All date/time libraries I've worked with return timestamps that are the number of seconds (or milliseconds) since Jan 1st 1970 UTC. Check the documentation for the library you used to create the timestamp to be sure.
This means that you should be ok, unless you have used a date/time library that does not follow this convention, or somehow calculated the timestamps yourself and accounted for the timezone.
For example in JavaScript if you store the value returned from new Date().getTime() and later pass that value to new Date(...) on a different system you will end up with the same absolute date/time, regardless of the timezones of the two systems. The same goes for Ruby, do Time.new.to_i on one machine, and run Time.at(...) on another and you will get the same absolute date/time. When I say "absolute date/time" I mean that it's UTC time will be the same, most likely the system will display it in the local time zone, but that is what you want.
Some points to consider about date in Mongo:
All dates are stored in UTC in MongoDB
MongoDB stores dates internally as a 64 bit integer representing
milliseconds since 1970-01-01T00:00:00Z
If the date value you provide is not already in UTC it
will be converted to UTC before being stored in MongoDB by the driver
The recommendation is not to use DateTime.Parse.
You will get into all sorts timezone issues regarding how DateTimes are formatted.
Instead just use one of the DateTime constructors with UTC flavor.
Example:
var dateTime = new DateTime(2011, 5, 5, 0, 0, 0, DateTimeKind.Utc);
Hope you find it useful.