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?

  • Can you add the logic you use to retrieve this date value? – Adrian Larson Feb 7 '17 at 20:58
  • Added my code, which isn't much. – Michael Sobczak Feb 7 '17 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). – Jesse Milburn Feb 7 '17 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. – Michael Sobczak Feb 7 '17 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. – Jesse Milburn Feb 7 '17 at 21:20
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.

| improve this answer | |
  • 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'. – Michael Sobczak Feb 7 '17 at 21:28
  • Sorry you need to pass it the timezone id, not the display name. Added that to the answer. – Jesse Milburn Feb 7 '17 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. – Michael Sobczak Feb 7 '17 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() – Jesse Milburn Feb 7 '17 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
| improve this answer | |
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;
    }
| improve this answer | |
  • The original value is a Date field, which by definition has a "00:00:00" time. – Michael Sobczak Feb 8 '17 at 19:34
  • No, the actual field in the Salesforce custom object is defined as Date. The solution I posted works just fine. – Michael Sobczak Feb 8 '17 at 23:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.