Parsing date to remove timezone - java

I use the following SimpleDateFormat to parse a string,
SimpleDateFormat ft= new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
String notimeZone = ft.format(startDateTime);
Date date = ft.parse(notimeZone);
startDateTime is Date object with value in format "Thu Mar 06 12:27:55 IST 2014".
in notimeZone variable i get, Thu Mar 06 12:27:55 2014
I am expecting output in variable date as, Thu Mar 06 12:27:55 2014
But am getting same , Thu Mar 06 12:27:55 IST 2014.
How to remove the time zone from the date object.
Please help.

java.util.Date does not have a Timezone. It is not aware of TimeZone.
When you print, java picks up the default time zone.
Conceptually, you cannot have a date time without timezone. A date time has to be in one and only one zone. You may convert it to other zones, but it can never be without a zone.
If your business use case requires awareness of Time Zone, I would prefer to use Calendar class, or Joda Time. Avoid playing with Date class. If your business use cases do not require any time zone awareness, then go ahead with date. Assume all Date instances are in your default time zone.
Best thing is to use Calendar (or Joda Time). Calendar is a bit unintuitive but you will be able to get your job done. It is not without reason that Date class is mostly deprecated.
Initialize your Calendar with Timezone (check out available constructors). Use Dateformat to convert and show in UI in whatever time zone you wish to. I posted some code in your previous question. That might help you. I was stuck in a similar problem. I have dates in the DB in one time zone. To display them in another time zone on UI, you need to convert that datetime to another zone.

The following format gives
"EEE MMM dd HH:mm:ss z yyyy"->Thu Mar 06 13:18:02 IST 2014.
"EEE MMM dd HH:mm:ss yyyy" -> Thu Mar 06 13:18:02 2014.
Check if you gave a 'z' by mistake in the date format string.
For more details, Refer - http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Related

Converting from one time format to the other

Is it possible to convert this date string using Java time package
3-6-2017
to this format
"Mon Mar 6 00:00:00 EST 2017"
I created these two formatters, but which time instance should I use? I've tried LocalDate, LocalDateTime, and ZonedDateTime.
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M-d-uuuu");
DateTimeFormatter convertedToFormat = DateTimeFormatter.ofPattern("EEE MMM dd hh:mm:ss zzz yyyy");
I believe that you have three issues:
To accept month in either 1 or 2 digits (like 3 for March and 11 for November) you need to specify one pattern letter M, not two. Similarly for day of month. So your input format pattern string should be M-d-uuuu (or just M-d-u). Edit: You also need d instead of dd in the “converted to” pattern.
To print hour of day (from 00 through 23) you need uppercase HH. Lowercase hh is for clock hour within AM or PM from 01 through 12.
Since your input string did not contain time of day, you need to specify time of day some other way. Similar for time zone since your “converted to” format contains zzz for time zone abbreviation.
So in code I suggest:
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M-d-uuuu");
DateTimeFormatter convertedToFormat = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss zzz yyyy");
String input = "3-6-2017";
ZonedDateTime startOfDay = LocalDate.parse(input, inputFormat)
.atStartOfDay(ZoneId.of("America/New_York"));
String output = startOfDay.format(convertedToFormat);
System.out.println(output);
Output from my snippet is the desired:
Mon Mar 6 00:00:00 EST 2017
Or to answer your question a little more directly:
… which time instance should I use?
You need two of them: LocalDate for parsing your input and ZonedDateTime for formatting your output. And then a conversion between the two. The one-arg atStartOfDay method provides the conversion we need. (There is a trick for parsing directly into a ZonedDateTime using default values for time and time zone, but it’s more complicated.)
There are other time zones that will also produce EST as time zone abbreviation. Since your profile says you’re in Boston, I think that America/New_York is the one you want.

How to change timezone without changing the time?

I have a timestamp 2018-01-01 18:20:23.11 which is in UTC. I need to print this in a different format but retain the UTC timezone. However if I use SimpleDateFormat ("dd MMM YYYY yyyy kk:mm z"), it takes my current timezone and gives me 01 Jan 2018 18:20 EST. I want this to print 01 Jan 2018 18:20 UTC. Doing a Timezone.getTimeZone("UTC") converts this time to UTC (does a +4 to hours)which is not the desired result.
DateTimeFormatter originalFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SS");
DateTimeFormatter newFormatter
= DateTimeFormatter.ofPattern("dd MMM uuuu HH:mm z", Locale.ENGLISH);
String originalTimestamp = "2018-01-01 18:20:23.11";
String differentFormat = LocalDateTime.parse(originalTimestamp, originalFormatter)
.atZone(ZoneId.of("Etc/UTC"))
.format(newFormatter);
System.out.println(differentFormat);
This prints
01 Jan 2018 18:20 UTC
ZoneId.of("Etc/UTC") or ZoneOffset.UTC?
A possibly nerdy edit: I had first written .atZone(ZoneOffset.UTC) in the conversion. I usually use ZoneOffset.UTC to denote UTC and consider this the nice and idiomatic way of specifying it. However in the case of your code, this resulted in the zone being given as Z in the output where you had asked for UTC. Using ZoneId.of("Etc/UTC") instead gives you what you want. I can find no other way of making sure that the zone is formatted as UTC (save hardcoding UTC in the format pattern string, but that would be an ugly hack).
BTW ZoneId.of("Etc/UTC").normalized() returns ZoneOffset.UTC (at least on my Java 10, but I expect it to be the case always).
SimpleDateFormat vs. java.time
SimpleDateFormat is not only long outdated, it is also notoriously troublesome. I recommend you avoid it. It is correct, as you have observed, that it uses your JVM’s default time zone. There is a way to persuade it to do differently, but I would not bother.
java.time is the modern Java date and time API. It came out in 2014 as a replacement for the old and poorly designed date and time classes. IMHO it is so much nicer to work with.
Link: Oracle tutorial: Date Time explaining how to use java.time

Dateformat converting IST to GMT

Problem in converting IST to GMT.
DateFormat df = new SimpleDateFormat("HH:mm:ss z");
String input = "05:30:00 IST";
Date d = df.parse(input);
Calendar c = Calendar.getInstance();
c.setTime(d);
System.out.println(c.getTime());
getting Thu Jan 01 03:30:00 GMT 1970 as output instead of Thu Jan 01 00:00:00 GMT 1970
You should be wary of using three-letter abbreviations of timezones because they are ambiguous. In this case, IST could refer to:
Indian Standard Time (UTC+0530)
Israel Standard Time (UTC+02)
Irish Standard Time (UTC+01)
Wikipedia lists some common timezone abbreviations; examples of other ambiguous common abbreviations are:
AM(S)T
AST
BST
CDT
CST
ECT
FKST
GST
MST
It is better to use either a UTC offset (e.g. +0530 for Indian Standard Time) or a uniquely-defined timezone identifier (e.g. Asia/Calcutta)
There are a number of things wrong with what you seem to be trying to do here.
You are trying to use a java.util.Date object to contain just a time-of-day (hours, minutes, seconds). A java.util.Date object is not suitable for that purpose. A java.util.Date object is really a timestamp - it represents an "absolute" moment in time, counted as a number of milliseconds since 01-01-1970, 00:00:00 GMT.
A java.util.Date object does not contain timezone information. You cannot convert a Date object from one timezone to another timezone, because the Date object simply does not contain information about a timezone.
Converting a time-of-day from one timezone to another cannot be done if you only know the hours, minutes and seconds. The result also depends on the date (year, month, day) - the results can be influenced by daylight savings transitions. So it's not possible to convert a time-of-day from one timezone to another if you don't know the date.
If you use the Java 8 java.time API, then it's easy; use ZonedDateTime, which does contain information about the timezone.
// Assuming that with "IST" you mean India Standard Time
ZonedDateTime input = ZonedDateTime.of(2015, 3, 23, 5, 30, 0, 0, ZoneId.of("Asia/Calcutta"));
System.out.println(input);
ZonedDateTime output = input.withZoneSameInstant(ZoneId.of("GMT"));
System.out.println(output);
If you want to use the old java.util.Date and java.util.Calendar API, then you set the timezone on the DateFormat object that you use to display the date - not on the Date object itself:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
cal.set(2015, Calendar.MARCH, 23, 5, 30, 0);
Date input = cal.getTime();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
System.out.println(df.format(input));
df.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(df.format(input));

Calendar object in Java, returns wrong time?

So I've been working on a simple little method which would return a String as Calendar object.
Here's what I have:
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH);
try {
cal.setTime(sdf.parse(this.getCreated_at()));
}
catch (ParseException e) {
e.printStackTrace();
}
return cal;
Now assuming that the String obtained from this.getCreated_at()) is always in the desired format, this should, theoretically, work perfectly.
There's only one little hiccup.
Assume that this.getCreated_at()) returns Mon Feb 10 18:52:54 +0000 2014. Shouldn't be a problem right? The format is correct, and everything.
However when I have my main method do as follows:
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
System.out.println(sdf.format(... ... ....stringToCalendar().getTime()));
It gives me the following output:
ma feb 10 19:52:54 +0100 2014
My problem, as you may have noticed, is that firstly, the time is wrong. It's added an hour.
Secondly, it's translated the text fields Mon and Feb into ma and feb which are translations to Norwegian, the place from where I'm coding now.
I need the time returned to me as a Calendar object, in the exact manner which it was obtained from the this.getCreated_at())-string.
What am I doing wrong?
Can anyone help me out?
I'm from Norway, by the way. That's +01:00 Standard Offset.
My problem, as you may have noticed, is that firstly, the time is wrong. It's added an hour.
No it hasn't. Not really. It's displaying the exact same time, but in your local time zone. Unfortunately you can't easily determine the original time zone, because DateFormat.parse returns a Date, which doesn't contain any time zone information. (In this case you don't really know the full time zone anyway - you just know the UTC offset, which isn't quite the same thing.)
EDIT: As noted in Joni's answer, it appears that DateFormat.parse does retain the original information in the format's calendar; you wouldn't want the time zone, but you could use the offset stored in the Calendar object. Personally this seems to me to be an implementation detail which I wouldn't want to rely on (especially as you end up with an offset which isn't necessarily supported by the time zone in the same calendar object!) but you could mangle it if you really wanted.
Secondly, it's translated the text fields Mon and Feb into ma and feb which are translations to Norwegian, the place from where I'm coding now.
That's because your SimpleDateFormat is using your default locale.
You can fix this part very easily:
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",
Locale.ENGLISH);
If you know what time zone you want to use, you can specify that on the SimpleDateFormat as well. Otherwise, you're going to have a slightly harder time.
I would recommend that instead, you start using Joda Time. That way you can parse the value as a DateTime, which "knows" which time zone it's in - so you can reformat it however you want, preserving the relevant time zone information.
Sample Joda Time code:
import java.util.*;
import org.joda.time.*;
import org.joda.time.format.*;
class Test {
public static void main(String[] args) {
DateTimeFormatter format = DateTimeFormat
.forPattern("EEE MMM dd HH:mm:ss Z yyyy")
.withLocale(Locale.ENGLISH);
String input = "Mon Feb 10 18:52:54 +0000 2014";
DateTime value = format.parseDateTime(input);
System.out.println(format.print(value));
}
}
You can get the Calendar instance from the date format:
sdf.parse(this.getCreated_at());
Calendar parsed = sdf.getCalendar();
This instance has the fields set to what was parsed: UTC timezone, time 18:52:54, etc...
Unfortunately there appears to be no way to format the values held by Calendar using SimpleDateFormat.

Is it possible to create a Calendar object like Tue Mar 03 13:43:00 (without time zone)?

I have a requirement of sending the calendar object with time zone, like Tue Mar 03 13:43:00. I know that Calendar object always return with Tue Mar 03 13:43:00 CST 2009, so how can I create it without the time zone?
You can use the DateFormat class (more specifically the SimpleDateFormat concrete subclass) to format the date however you want. Here is an example:
Calendar cal = Calendar.getInstance();
DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss");
String dateString = format.format(cal.getTime()));
Prints:
Fri Mar 06 15:50:26
It's not possible to have a Calendar object without a TimeZone. Really, that doesn't make any sense - Calendar seeks to represent "a specific instant in time" - how can you represent an instance in time without knowing what TimeZone the time you are representing is in?
So, there's a few things to consider:
You say you need to pass this Calendar to some other component - does that API care what TimeZone the Calendars are in? Will that API ignore the TimeZone setting, use it to calculate a time difference against it's own local timezone, etc.?
Are you aware that you can easily change the TimeZone of a Calendar instance?
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getDefault()); // returns default TimeZone for your system
cal.setTimeZone(TimeZone.getTimeZone("EST")); // Eastern Standard Time
cal.setTimeZone(TimeZone.getTimeZone("Asia/Kolkota"); // UTC+5:30
Javadocs on Calendar, TimeZone.
You can use a simple Date object using;
Date d = new Date();
Date d2 = calendar.getTime();
Or the even simpler, time in milli-seconds.
long time = System.currentTimeMillis();
To avoid confusion over time zones, I suggest storing and setting all date/times as a standard time zone, such as GMT+0 and then converting the time for display etc as required.
Upon rereading your question and your comments on my other answer, it sounds like the problem is that you want the result to be a Calendar object, not a String. So it isn't a question of formatting the String representation of the Calendar.
In this case, what you are asking is technically impossible: all implementations of the Calendar class exist to represent an internal time, which is stored as the number of milliseconds since the Unix epoch (Jan 1 1970 00:00 GMT). The time "5:00 am" in Boston is different from "5:00 am" in Seattle--they have different internal timestamps.
Your best bet would be to use the same time zone everywhere, and probably GMT makes the most sense for that purpose:
cal.setTimeZone(TimeZone.getTimeZone("GMT+0000"));

Categories