I am trying to convert a string date value in java to date and trying to store it in a mysql table.
Below the code snippet:
DateFormat dfm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
String string = "07/24/2013 17:57:52 UTC";
Date a = dfm.parse(string);
System.out.println(a);
My problem is that the above code always returns the following console output:
Wed Jul 24 17:57:52 PDT 2013
I don't know why the time zone is getting changed, more over when I am trying to put this into the database then it is storing it in '2013-07-24 17:57:52' format. I am not sure why the above code is returning me timezone in PDT?
Can you guys please explain me that? My intent is to store a UTC date which will come as an input and store it into the MySQL timestamp field.
Thanks in Advance.
Right, if you can fix the string to not include the time zone, it's simpler. Firstly, you need to understand that a Date object doesn't contain a time zone at all - it's just a point in time.
Next, as we're trying to parse a date/time specified in UTC, you should set that in the SimpleDateFormat:
DateFormat dfm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
dfm.setTimeZone(TimeZone.getTimeZone("UTC"));
Now at that point I'd hope that JPA would do the right thing. You'd at least be passing the right value to the Timestamp constructor.
However, this part of the MySQL documentation makes me nervous:
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
It sounds like you may want to use a DATETIME field instead, to stop this time zone conversion. Setting the time zone of the connection to UTC would help when storing it, but you'd still need to worry about what would happen when fetching. (Databases are pretty messed up when it comes to date/time types, IMO. This is just another example of that...) On the other hand, if you're fetching the data back with Java as well, I'd hope that it would just work transparently. It's probably worth at least trying that...
You are missing the timezone part in your format string. "UTC" is therefore ignored.
Try this:
DateFormat dfm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss z"); // added "z"
// then the rest of your code as-is
String string = "07/24/2013 17:57:52 UTC";
Date a = dfm.parse(string);
System.out.println(a); // prints "Wed Jul 24 19:57:52 CEST 2013" for me
Further to #JonSkeet 's word of warning, MySQL "current time zone" can be checked or changed through the time_zone session variable.
Either make sure your session is set to UTC (SET time_zone = '+0:00'), or use a DATETIME type instead.
Related
I run the following code:
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
try{
Date date = sdf.parse("03-28-2003 01:00:00");
System.out.print(date.toString());
}
catch(Exception e){
//do something
}
The result of the parsing is this date: 2003-03-28T02:00:00.000+0300
One hour is added.
When I change the year/day/hour to any other valid number, I get the correct time, no extra hour is added. If I only change the minutes or the seconds I still get the added hour.
Can anyone tell me why this happens?
EDIT:
This is related to when daylight saving time is applied in the timezone my program runs on- UTC+02:00.
In this timezone the clock changed on 2003-03-28. that's why an hour was added, as it was suggested by the comments and answer below.
I used the code suggested in the answer to parse my date and the parsing worked! The date is parsed correctly, the extra hour isn't added.
Finding out exactly what your code does is complicated by the fact that not only SimpleDateFormat.parse() may depend on the default time zone of the computer (and does in this case where the pattern does not include time zone), also Date.toString() depends on the default time zone. However, I understand that you want to interpret the date string in UTC, so I will concentrate on getting the parsing right and not worry so much about what’s printed.
Feek is correct in the comment that setting the time zone of the SimpleDateFormat to UTC will get you what you want, for example:
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
With this line added before try I get this output on my computer:
Fri Mar 28 02:00:00 CET 2003
2 am. CET agrees with 1 UTC, so now the parsing is correct.
Allow me to add that if you can use the Java 8 date and time classes, I find the corresponding code somewhat clearer:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse("03-28-2003 01:00:00", formatter);
OffsetDateTime utcDateTime = dateTime.atOffset(ZoneOffset.UTC);
System.out.println(utcDateTime);
The point is not that it’s shorter, but that you don’t get easily in doubt about what it does and don’t easily get time zone or DST problems. An added benefit is that the output is also as expected:
2003-03-28T01:00Z
Now it’s evident that the time is correct (Z means Z or Zulu or UTC time zone, it’s got more than one name).
If for some reason you absolutely need an oldfashioned java.util.Date object, that is not difficult:
Date date = Date.from(utcDateTime.toInstant());
This gives the same date as we got from sdf.parse() with UTC time zone.
In a chat application, the server gave me this info regarding on the date that the message was created
2015-05-04 09:56:27
DateTime instance gives me this 2015-05-04T09:56:27.000+08:00
What I wanted to display on the chat bubble is this format
hh:mm a
My code doesn't seem to display the hours and minutes I wanted, instead it displays the hours and minutes in UTC
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dt = formatter.parseDateTime(strDate);
String str = String.format("%s:%s %s",
dt.toString("hh"),
dt.toString("mm"),
dt.toString("a")
);
it displays like this 09:56 am instead of 5:56 pm. It seems like the +8 offset wasn't counted. I have tried the withOffsetParsed and it doesn't work too
DateTimeFormatter df = formatter.withOffsetParsed();
DateTime dt2 = df.parseDateTime(strDate);
Is there anything I missed?
If DateTime outputs 09:56:27.000+08:00, then that is your local time- and the UTC time is 1:56am.
However, if your expectation that this should output 5:56pm is correct, something else is wrong. The server is giving you a timestamp without a timezone specified, which is a bad API. Presumably this time should be interpreted as UTC?
Try adding .withZoneUTC() to the creation of the DateTimeFormatter. This will make it interpret the time fields of the string as UTC and should produce a DateTime of 09:56:27.000Z. You'll then need to convert this is a DateTime in your local timezone to display it, by calling .withZone(DateTimeZone.getDefault()) (or whatever means you have to get the appropriate timezone for the user, for example)
(You could be pedantic and call parseLocalDateTime to get a LocalDateTime since that is what the server is sending, but personally I'd just encapsulate the UTC rule into the formatter and pull a full DateTime straight out)
I'm reading information from a file (.csv) that will be inserted to a database after validation and approval from the end user. The text file is read, validated and its information loaded to a List containing forms which are used to check if the data already exist in database.
The problem arises when parsing the String to Date. The SimpleDateFormat.parse() method returns an unexpected date format even when the pattern for SimpleDateFormat is "yyyy-MM-dd".
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
Parsing the loaded values to the travel object:
travel.setDate( dateFormat.parse( form.getTravelDate() ));
In debugger the form shows the date as:
"2012-12-12"
It is read as intended. However when parsed becomes:
Wed Dec 12 00:00:00 CST 2012
I've spent the whole day trying to solve this but I'm out of ideas at this point. Afaik the pattern is alright and I've tried adding a locale to no avail.
Edit: the problem is when I need to insert the values to the database using Hibernate. The not desired format also ends up showing in the Database.
The data is show in a .jsp page using
HttpServletRequest("table",travelList);
The date format I don't need shows here, when in the past this issue never happened. At last the information is sent to the database where the problem persists.
No, it "becomes" a java.util.Date value. If you're then converting it back to a string by calling Date.toString(), you should consult the Date.toString() documentation for what to expect.
The value stored in the Date is just a point in time - the number of milliseconds since the Unix epoch. There's no format in there, no time zone etc. It also doesn't know that it was only a date value rather than a date and time (the naming of Date is one of the many unfortunate aspects of the API).
It's crucial that you mentally separate "the result of the parse operation" from "the string value that is used to represent that result if I call toString"".
I'd also advise you to set the time zone on your SimpleDateFormat to UTC when parsing a date - that way you know that you can't possibly have any ambiguous or skipped times leading to hard-to-predict behaviour. (Of course, you then need to know that you'll have parsed the date to "the start of the UTC date" and handle it appropriately elsewhere.)
You need to use the formatter when printing the Date as well.
dateFormat.format( travel.getDate() );
When your parse the String using a DateFormat, you get a complete Date object with the time units missing in the string initialized to zero. In your example, that's hours, minutes and seconds.
By default, if you do not use a formatter, Date's default string representation (provided by its toString() method) gets printed.
Parsing doesn't mean it format, it simply parse it as text to a java.util.Date object. See parse method in documentation.
You need to use the format method.
dateFormat.format(travel.getDate())
See documentation for more details.
if form.getTravelDate() is returning String then First Parse the Date from String
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
Date parsedDate=dateFormat.parse(form.getTravelDate());
// Here parsedDate is in form Wed Dec 12 00:00:00 CST 2012
Now Format the Date using the Same SImpleDateFormat to get the desired output
System.out.println(dateFormat.format(parsedDate));
Your Desired Output
2012-12-12
Update
Assuming data Type of Columns in which we insert this data in Database is of Date Type not varchar then use the below statement
travel.setDate(dateFormat.format(parsedDate));
As I understand parse method returns Date. Below is the parse method syntax.
public Date parse(String source)
throws ParseException
So, you need to parse the string date and store into a Date variable. Then format the Date variable using SimpleDateFormat.
//getTravelDate is "2012-12-12"
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
Date dtObj=new Date();
dtObj=dateFormat.parse(form.getTravelDate()); //Store in date variable
System.out.println(dateFormat.format(dtObj)); // Now format the date object
The final output will be 2012-12-12. Hope it will help you.
I'm using Java 6. Our servers are on Eastern Standard Time (GMT-5), and I'm trying to store a value that should be interpreted as such but I'm confused about how to convert it. I have
String dateStr = "1368921600000"; // This is 5/19/2013 00:00:00
final Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("GMT-5"));
cal.setTimeInMillis(Long.parseLong(dateStr));
final java.util.Date dateObj = cal.getTime();
System.out.println(dateObj.toString());
but right now this prints out "Sat May 18 19:00:00 CDT 2013" (since my local machine is on CDT) but I want the result to be "Sat May 18 24:00:00 CDT 2013". How can i interpret the date string "1368921600000" as an EST date? Thanks, - Dave
1368921600000 is an instant in time, the same instant, everywhere in the world. To convert this to a date and time, you have to specify where in the world you want to know the date/time at that instant. It just so happens that the timestamp is relative to UTC, and is Sun, 19 May 2013 00:00:00 GMT.
If you want the time of this instant (the same instant) somewhere else in the world, you can use the Calendar as you did and extract the individual field values (e.g. HOUR_OF_DAY). If all you care about is getting a text string, you use a DateFormat instance such as SimpleDateFormat:
DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
df.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String timeOnUSEastCoast = df.format(new Date(1368921600000L));
// will be GMT-5 or GMT-4 depending on DST
In this example, the output would be GMT-4: Sat, 18 May 2013 20:00:00 EDT (not only has the hour changed, but it's still the previous day on the US east coast).
If you want to output the UTC time but just want to pretend it's EST then it's just easier to tell the DateFormat to leave off the time zone field (remove the "z") in the text output and call it whatever you want, but understand that the timestamp value is always UTC.
It is often not necessary to use the Joda Time library to get historically accurate time-zone- and daylight-savings-aware local time mappings, although this is the common go to response for many.
If you have a database of timestamps that require local time conversion, then here are some principles that have served me well:
Store date/times (Instants, in the parlance of Joda; Dates, in the parlance of the Java Calendar API) in UTC time. UTC does not care about DST. It does not care about time zones. UTC simply represents a universally representable moment in time. This step alone can save a lot of date/time headaches.
Database records should contain TimeZone and/or Locale fields so that mapping from UTC can be performed. Think about your data. Every timestamp in your database does not need time zone information associated with it. Instead, associate the time zone data with a part of your data model that provides appropriate granularity. If your app will only ever be localized in one time zone, then you needn't store this infor at all. In my recent project, I created a Locale table that contains the TZ ID for timestamps in my Encounters table. All other timestamps are subordinate to these records, so it made sense to associate it there.
Use the Java API GregorianCalendar to map UTC Dates to local time. And that's all I ever use it for. I almost never use GregorianCalendars to do date arithmetic or other date operations. Here is the paradigm that I've been working with:
public static void main(String[] args) {
m_GregorianCalendar = new GregorianCalendar(TimeZone.getTimeZone(
"America/Chicago"));
Date d = new Date();
String fmt = "dd-MMM-yyyy # HH:mm";
:
:
String myDate = mapToLocalTime(d, fmt, gc);
:
:
}
public String mapToLocalTime(Date utc, String format, GregorianCalendar gc) {
gc.setTime(utc); // this calendar is already timezone aware (constructed
// with time zone id (DST too))
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setCalendar(gc); // formatter uses conventions of calendar
sdf.applyPattern(fmt); // pattern for formatter
return sdf.format(utc);
}
Consider representing timestamps internally in a numeric format (longs, doubles). This greatly simplifies date comparisons and date arithmetic. The only downside is that conversions must be done to format the data into a human recognizable form, but if you use functions for these conversions it need not be a big deal at all.
Use either a new java.util.SimpleDateFormat(format) or java.util.DateFormat.getDateTimeInstance(int,int), then use #setTimeZone(timezone).
When you're printing Date.toString(), the Calendar's time zone is not taken into consideration at all. After you do a cal.getTime(), whatever was set in Calendar is no longer relevant.
What is is TimeZone's default time zone.
So right before printing the date, set the default time zone to the one you want to print in, e.g.:
String dateStr = "1368921600000"; // This is 5/19/2013 00:00:00
final Calendar cal = Calendar.getInstance();
TimeZone gmtZero = TimeZone.getTimeZone("GMT");
cal.setTimeInMillis(Long.parseLong(dateStr));
final java.util.Date dateObj = cal.getTime();
TimeZone.setDefault(gmtZero);
System.out.println(dateObj.toString());
This will print the date in GMT regardless of your system time zone.
Just remember to bring back the original default TimeZone afterwards!
I have a db, that stores dates in OleDateTime format, in GMT timezone. I've implemented a class, extending Date in java to represent that in classic date format. But my class is locale-dependent (I'm in GMT+2). Therefore, it converts the date in the db as date - 2 hours. How do I make it convert the date correctly? I want my class to be locale-independent, always using GMT timezone. Actually, the question is:
class MyOleDateTime extends Date {
static {
Locale.setDefault(WhatGoesHere?)
}
// ... some constructors
// ... some methods
}
Well, it's better to use the Calendar object like suggested in other answers. However, if you really want to set global timezone, you can use TimeZone.setDefault(TimeZone.getTimeZone("UTC")); early in your application code. There is also user.timezone Java system property.
Also (just fun to know), it appears that the only country actually living by GMT/UTC time (without daylight saving changes) is Liberia.
In fact, Date objects per se are always locale- and timezone-independent. Its getTime() method will always return the number of milliseconds passed since January 1, 1970 00:00:00 (not counting leap seconds) in UTC. But if you want to get something else than milliseconds, you have to use Calendar, which is timezone-dependent. But it is the right way to go. You don't use that deprecated methods in Date class, do you?
As Michael Borgwardt has already said, the Java Date object does not know anything about timezones. It's just a wrapper for a number of milliseconds since 01-01-1970 00:00:00 UTC.
You start dealing with timezones only when you for example convert the Date object to a String using a DateFormat. You set the timezone on the DateFormat to specify in which timezone you want to see the Date.
DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String text = df.format(date); // text will contain date represented in UTC
A Date is locale-independent, always using GMT timezone. It's just a wrapper around a millisecond timestamp in GMT (more correctly: UTC).
The only things in Date that are timezone dependant are the deprecated methods like getDay() - that's why they're deprecated. Those use the default time zone. The correct thing to do is to avoid using those deprecated methods - not to set the default timezone to UTC! That could cause problems elsewhere, and you can't prevent other parts of the code from setting the default timezone to something else.
Use a Calendar object:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"),
locale);
Here's a snippet I used to calculate the GMT offset from the Calendar instance and format it. I appreciate all the help I've gotten from this site, its nice to contribute. I hope this helps someone somewhere. Enjoy.
Calendar calInst = Calendar.getInstance();
//calculate the offset to keep calendar instance GMT
int gmtOffsetMilli = calInst.get(Calendar.ZONE_OFFSET);
long gmtOffsetHr = TimeUnit.HOURS.convert(gmtOffsetMilli, TimeUnit.MILLISECONDS);
calInst = Calendar.getInstance(TimeZone.getTimeZone("GMT " + gmtOffsetHr));