Insert/Retrieve Date as per local time zone in MongoDB using Java - java

I am inserting the current date in a mongodb collection using java.
I am using the following code to do so:
BasicDBObject doc = new BasicDBObject("date",new Date());
coll.insert(doc);
It is saving the date in GMT not in my local timezone.
But when I am inserting through shell using command:
db.test.insert({date:Date()});
It is taking my local timezone.
Is there any way to insert Date as per local time zone format using java
or any way to convert date to local timezone while retrieving.
Thanks & Regards

The java Date object is intentionally timezone-agnostic and supposed to represent GMT times (it internally stores its value as milliseconds since January 1, 1970, 00:00:00 GMT). I would really recommend you to work with this and internally handle all dates in GMT, because it saves you plenty of trouble with daylight saving time or when your application will be deployed in a distributed manner in multiple timezones.
To convert a Date object to or from strings representing it in the timezone of the user, use a SimpleDateFormat on which you called the setTimeZone method with the users TimeZone (the static method TimeZone.getDefault() gives you the time zone of the local system).

Related

Date to Timestamp with UTC in Java

I have to convert a date (that is already in UTC) to a java.sql.Timestamp.
Issue
But when doing that, the time is changed to machine time:
new Timestamp(date.getTime());
So I get another date on the server.
Expected
When I convert back to Date I want to have the same date as before conversion.
I want to keep the same date (in UTC).
How could I do that?
It does not change the time. Timestamp and Date don't have a concept of a timezone, they represent an instant of time since the Epoch(1970-01-01T00:00:00Z).
Their .toString() methods on the other hand, have the bad habit of applying the default timezone of the JVM, when generating the string representation. I would advise to stay away from those classes, and instead use java.time, the modern java datetime API, it's available since java 8.

Does the TIMESTAMP datatype of Oracle store dates adjusted as per the local timezone?

I have a java application that uses Spring JDBC to store data into Oracle. The data includes timestamps/dates which we use to query certain data in the future.
The date fields are defined like so in the DDL SQL file :
JobExecution {
START_TIME TIMESTAMP DEFAULT NULL ,
END_TIME TIMESTAMP DEFAULT NULL
...
}
Java code to update these fields looks like so :
lastJobExecution.setEndTime(new Date(System.currentTimeMillis()));
new Date(System.currentTimeMillis()) stores current time in UTC format as per documentation below. The documentation of System.currentTimeMillis() says that it returns the following :
the difference, measured in milliseconds, between the current time and
midnight, January 1, 1970 UTC.
The documentation of Date says the following :
Allocates a Date object and initializes it to represent the specified
number of milliseconds since the standard base time known as "the
epoch", namely January 1, 1970, 00:00:00 GMT.
Params: date – the milliseconds since January 1, 1970, 00:00:00 GMT.
See Also: System.currentTimeMillis()
However, when I connect to the oracle database using SQL developer, the date seems to be stored as per the local time and not UTC.
Questions :
Does Oracle TIMESTAMP adjust the date as per the local time? I can't find this explicitly written anywhere in the Oracle documentation.
If yes what would be the best way to handle this. One way could be to convert this to UTC every time I read the data from this table. Another way could be to store it in the UTC format itself.
No, the TIMESTAMP data type does not store any time zone information.
See Datetime Data Types documentation.
Oracle provides two timestamp data type supporting time zones:
TIMESTAMP WITH TIME ZONE
As the name implies it stores the timestamp with time zone information. Time zone can be give as region name (e.g. Europe/Zurich) or as UTC offset. Note, you cannot create an index on such column directly. Instead Oracle creates a virtual column of SYS_EXTRACT_UTC(<your column>) and index is created on this virtual column. You may need to adapt your queries accordingly.
Often when you work with time zones, then a common approach is to store all times as UTC times and the client converts it to local times. This is exactly provided by second data type:
TIMESTAMP WITH LOCAL TIME ZONE
In a TIMESTAMP WITH LOCAL TIME ZONE all values are stored at DBTIMEZONE (which defaults to UTC) but values are always displayed in current user session time zone.
Another note, all comparison (e.g. <, >, =, >=, <=) of TIMESTAMP WITH [LOCAL] TIME ZONE values are performed on according UTC value.

Java Date toString contains a timezone... Why?

I wrote some code today in VB6 which would get me the number of milliseconds since 1/1/1970, so I could then send the value off to a java application which would parse that value like new Date(Long.parse(milliseconds)). I understand that the milliseconds the Date(Long) is looking for is the number of milliseconds since epoch in GMT. The machine I am running on is on CDT here in the US. When I get the toString value of the date parsed from the milliseconds, this is the value I get:
Tue Aug 11 15:40:50 CDT 2015
Is the CDT just there because the local machines timezone is CDT? I just think its a little weird that the constructor for Date would assume that a date derived from the milliseconds since epoch in GMT would implicitly be in the local machines timezone, rather than being offset (in this case) by -5 hours.
Is the CDT just there because the local machines timezone is CDT?
The timezone for display purposes is based on the default time zone.
The millis in the Date is relative to epoch and it doesn't have a time zone of its own.
It is taken since 00:00 1/1/1970 GMT or if you prefer 17:00 12/31/1969 CDT.
would implicitly be in the local machines timezone
The use of the local time zone is for display purposes only. Use another time zone or serialize the Date and send it to a machine in another timezone and it will use the local timezone again.
You're correct it's showing CDT in the toString() because your locale indicates that is the correct timezone for you. The Date object itself doesn't care about timezones and is a glorified wrapper around the Unix epoch in milliseconds. Generally you should use toString() for debugging purposes, and use a date formatter to actually display dates to the user (optionally specifying an explicit timezone instead of the one specified by the user's locale).
The Javadoc for Date.toString() only specifies the format of the string, it doesn't actually say anything about which timezone is used. I wouldn't rely on toString() always returning the default Locale in every implementation of Java.
You can use a custom representation of a date by using the correct format
Read this post, it might help you
Change date format in a Java string
The number of milliseconds since epoch began is NOT in the timezone known as UTC. It is not in any time zone. The epoch value is the same in ALL time zones. That epoch millisecond value is the same in London as it is in New York or San Francisco for that instant in time.
The Date function always uses the current default time zone if you don't set one. So for you, yes, the local machines timezone is CDT. Again, the epoch value in CDT is exactly the same as everywhere else on the planet, so there is no real reason to pick UTC when your machine thinks it is in central time.

How to read timezone from 'timestamp with time zone' column?

I am unable to find a way to read timezone value in PostgreSQL column of type timestamp with time zone.
JDBC offers method java.sql.ResultSet#getTimestamp(int, java.util.Calendar)
but I must provide my own calendar. I have see no way to obtain that calendar from timestamp field I am reading.
I am working on system that stores time data of multiple timezones. I need to save data with timezone information, and be able to read that timezone back from database.
Is it possible without hacks like
storing timezone value in another field
storing date as string, like 'Wed 17 Dec 07:37:16 1997 PST'
I am using JDBC 41 (JDBC4 Postgresql Driver, Version 9.4-1201), java 8.
The PostgreSQL documentation here says that:
For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT).
So there is no need to "store the time zone [that corresponds to the timestamp value]" per se; the timestamp with time zone values are always stored as UTC.
Also, there is no need to "obtain the Calendar from the timestamp field". The purpose of the Calendar is for you to define the particular timezone that you want to work with in your Java application.
In other words, timestamp with timezone does not store values from various timezones (e.g., some in EST, others in PST, etc.), it converts everything to UTC when the timestamp values are inserted.
Accepted answer is true and accurate. timestamp with time type does not store timezone information in the field, and it is not possible to extract it.
If interested in timezone of the timestamp, it must be stored in separately (in other field, or in custom column type).
At first glance, it looks like that timezone may be extracted from timestamp with timezone using function extract(timezone from field), but it is not the case.
That function just gives 'time zone offset from UTC, measured in seconds'. Important (and not stated in documentation) part is that the offset is measured from current timezone (set by session SET SESSION TIME ZONE, or server timezone if not set). It is not offset that was used when saving field.

Starting a new project, how to setup UTC time correctly in java with hibernate and mysql

So I am starting a new project using java, hibernate and mysql (spring mvc).
At the database level, what column type should I use?
At the java level, I believe I should be using Joda time.
My users table will store their time offset, which I will then convert/format at the UI level using the UTC value from the database.
With hibernate, do I really need that joda time hibernate plugin or is adding joda time enough?
Can someone tell me what methods I will be needing, or an article that goes over things with source code?
I think you may define your column in database as TIMESTAMP and map in Hibernate using TimeStamp object.
Use SimpleDateFormat in Java side to get the date time string in UTC as below:
DateFormat formatter = new SimpleDateFormat("MM/DD/yyyy hh:mm a");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date(timeStamp.getTime());
String dateString = formatter.format(date);
System.out.println(dateString);
At database level you can use datetime or timestamp (in MySQL) as column type. In Java you should use java.sql.Timestamp.
Joda time is possible but not absolutely necessary.
You can store the database time values either as UTC or as local time. I highly recommend to you using UTC. In the jdbc connect string (i. e. in hibernate.cfg.xml) you can define if the date always is in UTC or in local time, and JDBC does a time zone conversion if necessary (other time zone than UTC or local time can't be defined on JDBC level and will be much trouble if used).
When done like this you don't need special methods for the time zone conversion except them of the Java classes Calendar, Timezone and DateFormat.

Categories