I need to format java XmlGregorianCalendar to "yyMMdd" string.
My implementation:
XMLGregorianCalendar date = getDate(); //getting the date
if (date != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
LOG.debug("Parsing date...");
LOG.debug("XML Date: " + date);
LOG.debug("XML Date timezone: " + date.getTimezone());
GregorianCalendar gc = date.toGregorianCalendar();
LOG.debug("Gregorian calendar: " + gc.toString());
LOG.debug("Gregorian calendar timezone id: " + gc.getTimeZone().getID());
Date d = gc.getTime();
LOG.debug("Date: " + d.toString());
String formatted = sdf.format(d);
LOG.debug("Formatted: " + formatted);
}
What I see in log:
Parsing date...
XML Date: 1943-04-15T00:00:00.000Z
XML Date timezone: 0
Gregorian calendar: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="GMT+00:00",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=1943,MONTH=3,WEEK_OF_YEAR=1,WEEK_OF_MONTH=1,DAY_OF_MONTH=15,DAY_OF_YEAR=1,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]
Gregorian calendar timezone id: GMT+00:00
Date: Wed Apr 14 20:00:00 EDT 1943
Formatted: 430414
April, 15 was parsed as April, 14. What I'm doing wrong? When I should set timezone?
It was parsed as midnight on April 15th UTC. It was then formatted as 8pm on April 14th EDT, which is correct as EDT is four hours behind UTC.
Note that Date.toString() always uses the local time zone - a Date object has no concept of which time zone it's in.
Your formatted value is also using the default time zone, as you haven't specified a time zone. The calendar value (gc) is in UTC, but when you format it, it will apply the time zone from the formatter (as you format the Date value, which doesn't have a time zone).
It's not clear what you were trying to achieve, but hopefully that will help. As an aside, I'd strongly recommend that you use Joda Time instead if you possibly can - it makes a lot of this much clearer.
Related
I am working on a date picker where there is a range of dates. I noticed that all of my dates are a day behind and while investigating the issue I narrowed down the problem to the SimpleDateFormat object. No matter what Unix time I give it it sets the date to the previous day. An example of this behaviour is
String myFormat = "MM/dd/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(myFormat);
Log.d(TAG, "Time Zone: " + cal.getTimeZone().getDisplayName());
Log.d(TAG, "Printable: " + sdf.format(0));
The output that I see in the logger is
Time Zone: UTC
Printable: 12/31/1969
Why does the formatter use December 31 instead of January 1st 1970?
Because the DateFormat also has a TimeZone (and your system isn't set to UTC). You can change it with DateFormat.setTimeZone(TimeZone). Something like
String myFormat = "MM/dd/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(myFormat);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Printable: " + sdf.format(0));
Output is (as you expected)
Printable: 01/01/1970
guys.
im newbie in using joda time api. so here is my question. Ive app server deploy somewhere in the western region and the date fixed to the particular time , Fri Feb 6 08:50:54 UTC 2015.
however, i try to use joda time zone to change the timezone to my country. it didnt worked out. i have run out of ideas. below is my code :
java.util.Date dateIn = new java.util.Date();
DateTime dateTimeUtc = new DateTime( dateIn, DateTimeZone.UTC );
System.out.println("date time utc : " + dateTimeUtc);
DateTimeZone timeZoneLos_Angeles = DateTimeZone.forID( "America/Los_Angeles" ); // Adjust time zone to United States.
DateTime dateTimeLos_Angeles = dateTimeUtc.withZone( timeZoneLos_Angeles );
System.out.println("los angeles date time : " + dateTimeLos_Angeles.toDate());
DateTimeZone timeZoneMalaysia = DateTimeZone.forID( "Asia/Singapore" );
DateTime dateTimeKL = dateTimeLos_Angeles.withZone( timeZoneMalaysia );
System.out.println("KL date time : " + dateTimeKL.toDate());
java.util.Date newDate = dateTimeKL.toDate();
System.out.println("after convert to j.u.Date : " + newDate);
the output:
date time utc : 2015-02-06T08:58:29.127Z
los angeles date time : Fri Feb 06 16:58:29 SGT 2015
KL date time : Fri Feb 06 16:58:29 SGT 2015
after convert to j.u.Date : Fri Feb 06 16:58:29 SGT 2015
i dont know what's going on now. joda time is using my local machine time.
can u guys explain what is happening here? am i accessing joda time in wrong way. or is it my mistake?
A java.util.Date is basically the same thing as a joda-time Instant: an instant on the universal time scale. It doesn't have any time zone. It's just a number of milliseconds wrapped into an object. So when you call toString() on a java.util.Date instance, this object tries to make this number of millisecond readable to you, and transforms it to a readable date using the default timezone of the JVM: SGT in this case.
If you want to see a date in a given timezone, then print the DateTime instance itself (which contains an instant and a time zone) instead of transforming it to a Date (which loses the timezone information), or use a SimpleDateFormat configured with the timezone you want to display the java.util.Date to a string in the wanted time zone.
Joda Time provides a quality replacement for the Java date and time classes. The design allows for multiple calendar systems, while still providing a simple API. Converting a Joda DateTime object from one timezone to another is pretty easy and saves you quite a number of lines of code. See method below.
public static Date convertJodaTimezone(LocalDateTime date, String srcTz, String destTz) {
DateTime srcDateTime = date.toDateTime(DateTimeZone.forID(srcTz));
DateTime dstDateTime = srcDateTime.withZone(DateTimeZone.forID(destTz));
return dstDateTime.toLocalDateTime().toDateTime().toDate();
}
Since Joda Time has its own class for storing Date and Calendar objects, the DateTime class has its own toDate() method for converting it to a java.util.Date.
For further example check this link
I reused your code and did some changes. The commented lines were the previous implementation so that you can compare the difference with the new implementation.
Date dateIn = new Date();
DateTime dateTimeUtc = new DateTime( dateIn, DateTimeZone.UTC );
System.out.println("date time utc : " + dateTimeUtc);
DateTimeZone timeZoneLos_Angeles = DateTimeZone.forID( "America/Los_Angeles" ); // Adjust time zone to United States.
//DateTime dateTimeLos_Angeles = dateTimeUtc.withZone( timeZoneLos_Angeles );
DateTime dateTimeLos_Angeles = dateTimeUtc.withZone(timeZoneLos_Angeles);
//System.out.println("los angeles date time : " + dateTimeLos_Angeles.toDate());
System.out.println("los angeles date time : " + dateTimeLos_Angeles.toLocalDateTime().toDate());
DateTimeZone timeZoneMalaysia = DateTimeZone.forID( "Asia/Singapore" );
DateTime dateTimeKL = dateTimeUtc.withZone(timeZoneMalaysia);
//System.out.println("KL date time : " + dateTimeKL.toDate());
System.out.println("KL date time : " + dateTimeKL.toLocalDateTime().toDate());
//Date newDate = dateTimeKL.toDate();
Date newDate = dateTimeKL.toLocalDateTime().toDate();
System.out.println("after convert to j.u.Date : " + newDate);
I hope this one works for you. If you can optimize this code further then great. Cheers!
I'm working on a security signature in java that also verifies the date and time the call is being made. The POST call arrives with something like
String date = "Sat, 27 Apr 2013 01:11:30 GMT"
SimpleDateFormat RFC1123Format = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US);
And I'm able to parse it
Calendar gmtTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dateHeader = RFC1123Format.parse(date);
gmtTime.setTime(dateHeader);
System.out.println("Date Header (GMT TIME): " + gmtTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (GMT TIME): " + gmtTime.get(Calendar.HOUR_OF_DAY));
Calendar currentTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
currentTime.setTimeInMillis(System.currentTimeMillis());
System.out.println("System Date (LA TIME): " + currentTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (LA TIME): " + currentTime.get(Calendar.HOUR_OF_DAY));
currentTime.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("System Date (GMT TIME): " + currentTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (GMT TIME): " + currentTime.get(Calendar.HOUR_OF_DAY));
System.out.println("Diff: " + Math.abs(gmtTime.getTimeInMillis() - currentTime.getTimeInMillis()));
However the printout I get differs by 1 entire hour.
Date Header (GMT TIME): 1367025090000 ms
Hour of day (GMT TIME): 1
System Date (LA TIME): 1367022298441 ms
Hour of day (LA TIME): 0
System Date (GMT TIME): 1367022298441 ms
Hour of day (GMT TIME): 0
Diff: 2791559
Any ideas?
You can use JodaTime >> http://joda-time.sourceforge.net/ that implements TimeZone Calculations more efficiently than Java calendar
You don't give your formatter the calendar that you are using to represent your timestamps.
In this case, your calendar is set to represent timestamps in GMT. GMT is a synonym for UTC and UTC never observes any adjustment for DST. Your formatter, however, by default must convert your supplied string with the system default calendar as the basis, which likely does observe DST.
If this is the case, you can get consistent reporting by making sure that your formatter is using the same calendar that you are using to represent your date/times. Try this:
SimpleDateFormat RFC1123Format = new SimpleDateFormat();
GregorianCalendar gc - new GregorianCalendar(TimeZone.getTimeZone("GMT"));
RFC1123Format.setCalendar(gc);
RFC1123Format.applyPattern("EEE, dd MMM yyyyy HH:mm:ss z");
gc.setTime(RFC1123Format.parse(yourDateString));
Fixed it myself by adding an extra verification to check if Daylight Savings is being observed. This is the final code:
Calendar gmtTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dateHeader = RFC1123Format.parse(date);
gmtTime.setTime(dateHeader);
Calendar currentTime = Calendar.getInstance();
currentTime.setTimeInMillis(System.currentTimeMillis());
boolean DST = false;
if(currentTime.getTimeZone().inDaylightTime(currentTime.getTime())) {
DST = true;
}
currentTime.setTimeZone(TimeZone.getTimeZone("GMT"));
if(DST) {
currentTime.set(Calendar.HOUR_OF_DAY, currentTime.get(Calendar.HOUR_OF_DAY) + 1);
.
.
.
<code to handle last day of month and month change as a result of the hour adjustment>
}
Thanks #gangqinlaohu for your suggestion.
In my web application, I am storing all end-user's date information as UTC format in database, and before showing it to them, just converting the UTC dates to timezones of their choice.
I am using this method to convert a localtime to UTC time (while storing):
public static Date getUTCDateFromStringAndTimezone(String inputDate, TimeZone timezone){
Date date
date = new Date(inputDate)
print("input local date ---> " + date);
//Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
long msFromEpochGmt = date.getTime()
//gives you the current offset in ms from GMT at the current date
int offsetFromUTC = timezone.getOffset(msFromEpochGmt)*(-1) //this (-1) forces addition or subtraction whatever is reqd to make UTC
print("offsetFromUTC ---> " + offsetFromUTC)
//create a new calendar in GMT timezone, set to this date and add the offset
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"))
gmtCal.setTime(date)
gmtCal.add(Calendar.MILLISECOND, offsetFromUTC)
return gmtCal.getTime()
}
And this method for converting UTC date to local (while showing):
public static String getLocalDateFromUTCDateAndTimezone(Date utcDate, TimeZone timezone, DateFormat formatter) {
printf ("input utc date ---> " + utcDate)
//Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
long msFromEpochGmt = utcDate.getTime()
//gives you the current offset in ms from GMT at the current date
int offsetFromUTC = timezone.getOffset(msFromEpochGmt)
print("offsetFromUTC ---> " + offsetFromUTC)
//create a new calendar in GMT timezone, set to this date and add the offset
Calendar localCal = Calendar.getInstance(timezone)
localCal.setTime(utcDate)
localCal.add(Calendar.MILLISECOND, offsetFromUTC)
return formatter.format(localCal.getTime())
}
My question is, if the end-user is within a DST zone, then how do I improve the methods to accommodate their local clock times perfectly.
If you use a custom time zone ID, like GMT+10 you will get TimeZone that does not support DST, eg TimeZone.getTimeZone("GMT+10").useDaylightTime() returns false. But if you use a supported ID eg "America/Chicago" you will get a TimeZone that supports DST. The full list of supported IDs is returned by TimeZone.getAvailableIDs(). Internally Java stores time zone info in jre/lib/zi.
I am trying to convert a formatted date String to Date object. Date String is formatted to some other timezone.
When I do sdf.parse(String) it returns me my System date object.
Code is as below,
static Date convertGMTTime(String timeZone, long longDate){
Date convertedTime = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try{
Date date = new Date(longDate);
System.out.println("timezone: "+timeZone +", timestamp: "+date);
Locale locale = Locale.ENGLISH;
TimeZone destTimeZone = TimeZone.getTimeZone(timeZone);// TimeZone.getDefault();
System.out.println("Source timezone: "+destTimeZone);
/* DateFormat formatter = DateFormat.getDateTimeInstance(
DateFormat.DEFAULT,
DateFormat.DEFAULT,
locale);
formatter.setTimeZone(destTimeZone);*/
sdf.setTimeZone(destTimeZone);
String convertedDateStr = sdf.format(date);
System.out.println("convertedDateStr: "+convertedDateStr);
convertedTime = sdf.parse(convertedDateStr);
System.out.println("convertedTime: "+convertedTime + "sdf: "+sdf.getTimeZone());
}catch(Exception e){
e.printStackTrace();
}
return convertedTime;
}
I would appreciate if anyone could help and point out where I am going wrong.
Thanks in advance.
Output:
timezone: Atlantic/Cape_Verde, timestamp: Tue Jun 26 17:38:11 IST 2012
Source timezone: sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
convertedDateStr: 2012-06-26 11:08:11
convertedTime: Tue Jun 26 17:38:11 IST 2012
sdf:sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
Some more details to share, When I use another sdf object(without setting timezone for it), It do return me correct time and date but still timezone is picked from System clock
Code
static Date convertGMTTime(String timeZone, long longDate){
Date convertedTime = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdfParse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try{
Date date = new Date(longDate);
TimeZone destTimeZone = TimeZone.getTimeZone(timeZone);// TimeZone.getDefault();
System.out.println("Source timezone: "+destTimeZone);
sdf.setTimeZone(destTimeZone);
String convertedDateStr = sdf.format(date);
System.out.println("convertedDateStr: "+convertedDateStr );
convertedTime = sdfParse.parse(convertedDateStr,new ParsePosition(0));
System.out.println("convertedTime: "+convertedTime + "sdf: "+sdf.getTimeZone());
}catch(Exception e){
e.printStackTrace();
}
return convertedTime;
}
Output
Source timezone: sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
convertedDateStr: 2012-06-26 12:24:56
convertedTime: Tue Jun 26 12:24:56 IST 2012
sdf: sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
I understand that when I do not assign timezone to sdf it takes System time zone, but why doesn't it show time in System time zone? I shows it in timezone as it was in String but Timezone is different.
Ans when I set timezone it returns date object as per my system time irrespective of the fact that sdf has some other time zone set.
Can anyone please explain the functional behavior for sdf.parse and sdf.format.
For me sdf.setTimeZone() does have its impact when we use format and it is nullified when we use sdf.parse(). I find it quite strange.
Appreciate help in this regard.
You already have a Date (or the number of milliseconds of the Date), so there is nothing to convert. A Date doesn't have any time zone. It's a universal instant in time. The time zone is relevant only when you display this date, because the date 65647678000 could be 12:38 in some time zone, but 10:38 in some other time zone. It's also relevant when you parse the String representation of a Date, because 10:38 is 65647678000 in some time zone, but is 65657678000 in some other.
While you don't display a Date object, or parse a String to a Date, you don't need to care about time zones. And to choose the time zone used when displaying/parsing it, set the time zone of the DateFormat, and then use DateFormat.format()/DateFormat.parse() to format/parse the date.
When you use Date.toString() to display a date, it will always use your current time zone.
I find it easier to understand what I mean by not thinking of a Date as a day, a month, a year, an hour, etc., but as a moment: "when Kennedy was shot". "When Kennedy was shot" is the same moment for everyone. But if you represent the moment "when Kennedy was shot" in Dallas time zone, it's not the same result as the result you get when you represent this same moment in Paris time zone.