getBirthDate() returns java.util.GregorianCalendar with wrong timezome
jersoe-uri opened this issue · 3 comments
Our SF instance is set to America/New_York. I call getBirthDate() on a Contact with a birthdate that is set to 8/2/1983. It returns this object:
java.util.GregorianCalendar[time=428630400000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=1983,MONTH=7,WEEK_OF_YEAR=32,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=213,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=3600000]
Notice that the epoch is set to 428630400000. That is the correct date in GMT. I expected to either see that the timezone of the returned object was set to GMT instead of America/New_York, or that the epoch was set to 428644800000, which is 8/2/1983 in America/New_York.
Thanks for reporting this - we'll take a look into it.
The behavior is as expected firstly in above output the message mentions the DAY_OF_MONTH=1 instead of DAY_OF_MONTH=2 for the 8/2/1983 indicative of the fact the user entered the wrong date.
As a measure for checking this behavior went ahead and tested the getBirthDate() for both Enterprise and Partner Connections here is Pull Request for it.
https://gitcore.soma.salesforce.com/core-2206/core-public/pull/164134/files
The output for above case is as follows
java.util.GregorianCalendar[time=428716800000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=1983,MONTH=7,WEEK_OF_YEAR=32,WEEK_OF_MONTH=1,DAY_OF_MONTH=2,DAY_OF_YEAR=214,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=3600000]
The return type for the getBirthDate() is a java.util.Calendar datatype
In Java, Dates are internally represented in UTC milliseconds since the epoch (so timezones are not taken into account, that's why you get the same results for the epoch in milliseconds irrespective of the timezone WHICH IS DEFAULT JAVA BEHAVIOR FOR java.util.Calendar and not something WSC specifically controls it and thus is working as desired.
Please read the following articles to understand the behavior of java.util.Calendar in Java
- https://stackoverflow.com/questions/13470830/how-to-change-timezone-for-a-java-util-calendar-date
- https://stackoverflow.com/questions/7670355/convert-date-time-for-given-timezone-java%20.
- https://stackoverflow.com/questions/42161438/java-calendar-timezone-change-not-working-as-expected
To verify this behavior for the issue raised and to find the actual date that was set just use the epoch in this case 428716800000
and the timezone which was set here for the user it was America/New_York
which is also visible from the output for the getBirthDate() method for this example.
Just simply add the offset back to see the original Calendar value that was set to the milliseconds obtained to get back the proper output. (Recommended approach as per all the documentations above)
Solution for the issue above raised is to simply add the offset back while conversion represented below:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class SectoDate {
public static void main(String args[])
{
// milliseconds
long milliSec = 428716800000L;
// Creating date format
DateFormat simple = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZ");
simple.setTimeZone(TimeZone.getTimeZone("America/New_York"));
// Creating date from milliseconds
// using Date() constructor
Date result = new Date(milliSec);
// Formatting Date according to the
// given format
System.out.println(simple.format(result));
}
}
Giving the desired output 02 Aug 1983 20:00:00:000 -0400
on conversion
Closing the issue based on the explanation provided by @riyasurisalesforce in the above comment