0

I have a date field in a custom object that stores the following:

2016-01-01 00:00:00

That is what SF tells me the field value contains, when I output it using System.debug() in my Apex code.

Datetime d = priceList.Campaign_Effective_Date_Start__c;
System.debug ('Campaign_Effective_Date_Start__c - d = ' + d);

I need to get a formatted version of this date as:

01/01/2016

I've tried several ways to format the date, but I always end up getting:

12/31/2015

I've read some postings that state that I need to adjust the date to take into account my time zone offset. I'm not sure I understand why, since I'm OK with the date as it is stored in the SF database. I don't have a need to adjust it to take into account my current time zone, which is EDT (or 'America/New_York').

Is there a way I get the original date in formatted correctly, without having to manipulate it based on my current time zone?

5
  • Can you add the logic you use to retrieve this date value?
    – Adrian Larson
    Commented Feb 7, 2017 at 20:58
  • Added my code, which isn't much. Commented Feb 7, 2017 at 20:59
  • 1
    The time stored in SF is UTC, it is using your timezone EST which is -6 right now (I think) so it is rolling your date back. You need to use the Timezone class and calculate the offset. Or store the proper datetime. Or change your datetime to a date field (if you don't need the time element). Commented Feb 7, 2017 at 21:04
  • Unfortunately, SF doesn't provide a way to do this: Date d1 = priceList.Campaign_Effective_Date_Start__c; d1.format('MM/dd/yyyy'); I can't provide a format string with the Date.format(). Makes no sense to me. Commented Feb 7, 2017 at 21:06
  • 1
    Formatting is not the issue. 2016-01-01 00:00:00 stored in SF is GMT/UTC time. When you get the value it converts that value to the timezone set on your User record. So -6 hours, which is the previous day. 2015-12-31 18:00:00. Commented Feb 7, 2017 at 21:20

3 Answers 3

4

You need to calculate the offset of the time element of your Datetime object.

Note the second parameter is the Timezone id, not a SF id but a Timezone.getId()

public static Integer timeZoneOffset_hours(Date d, String timezoneId) {
    TimeZone tzSelected = TimeZone.getTimeZone(timezoneId);
    TimeZone tzGmt = TimeZone.getTimeZone('Greenwich Mean Time');

    Integer gmtOffset = tzGmt.getOffset(d);
    Integer selectedOffset = tzSelected.getOffset(d);
    Integer hours = (selectedOffset - gmtOffset) / 1000 / 60 / 60; 

    return hours;
}

Using this you can pass the date portion of your datetime object and the timezone you wish to convert to.

You can easily get the timezone id of the user to pass into the method:

UserInfo.getTimeZone().getId();

Then add the offset returned by the method to your datetime:

d.addHours(the offest);

Then format that value for the date.

4
  • When I run the following as Anonymous Apex in my IDE: Date d = Date.newInstance(2016,1,1); TimeZone tz = UserInfo.getTimeZone(); System.debug(tz.getDisplayName()); Integer i = StringUtils.timeZoneOffset_hours(d, tz.getDisplayName()); System.debug('i = ' + i); I get this: 'Eastern Standard Time', 'i = 0'. Commented Feb 7, 2017 at 21:28
  • Sorry you need to pass it the timezone id, not the display name. Added that to the answer. Commented Feb 7, 2017 at 21:56
  • I'm curious what the impact of the gmtOffset should be. For me, it always returns zero. Which makes sense, since the date value is stored by SF in GMT. Commented Feb 7, 2017 at 22:03
  • It should be -5 for you, EST is -5 from GMT. if you are not passing the timezone.getId() you will get a bad value. which was your problem from your first comment. Don't pass in tz.getDisplayName() pass in tz.getId() Commented Feb 7, 2017 at 22:07
1

Following Date functions will help you. Current Time displays in UTC time

Datetime currentTime = System.now();
Date currentDate = System.now().Date();

System.debug('current date=' + currentDate);
TimeZone tz = UserInfo.getTimeZone();
System.debug('Display name: ' + tz.getDisplayName());
System.debug('Current local time=' + currentTime.format('MM-dd-yyyy ') + ' ' 
  + currentTime.format('h:mm a'));

Use format function to display the datetime at current timezone.

USER_DEBUG|[2]|DEBUG|current time=2016-11-09 20:29:17
USER_DEBUG|[4]|DEBUG|Display name: Pacific Standard Time
USER_DEBUG|[6]|DEBUG|Current local time=11-09-2016  12:29 PM
0

This is what I came up with. It takes a Date input and returns it formatted in MM/dd/yyyy format.

public static String getFormattedDate(Date d) {
        String formattedDate = '';

        TimeZone tz = UserInfo.getTimeZone();

        Datetime dt = DateTime.newInstance(d.year(), d.month(), d.day(),0,0,0);

        Integer offset = tz.getOffset(dt);  System.debug('gmtOffset: ' + offset);
        Integer offsetHours = offset / 1000 / 60 / 60;

        if(offsetHours < 0 ) {
            dt.addHours(+(offsetHours));
        }

        formattedDate = dt.format('MM/dd/yyyy');

        return formattedDate;
    }
2
  • The original value is a Date field, which by definition has a "00:00:00" time. Commented Feb 8, 2017 at 19:34
  • No, the actual field in the Salesforce custom object is defined as Date. The solution I posted works just fine. Commented Feb 8, 2017 at 23:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .