Monday, September 15, 2008

Formating datetime variables in Apex

The current project I’m working on is a custom Visualforce page showing all of the scheduled maintenance activities my Support department has scheduled with our Customers. We have a custom object (Maintenance__c) which describes the details for the maintenance activity, including Start Date/Time and End Date/Time. I wanted to display this information in Calendar format using Visualforce. That way, my users can see, at a glance, what activities are scheduled throughout the month. I’ll show more of the application, as it develops, but for now I’ll focus on my first crisis.

The Problem: I wanted to display the current date in the subtitle of the section header. The code that does this is highlighted in the Page Editor section below, and the Visualforce page is right above it. It looks … fine. But I’m really, really fussy when it comes to page views. I didn’t like how the {!Today()} function returned “00:00:00 GMT” in the middle of the datetime output. Yuck! I wanted to see the information displayed in the “long date” format, just like I see in my Excel worksheets: “Monday, September 15, 2008”. I also didn’t like the fact that the datetime was GMT time, and my users would be mostly viewing this page from Eastern, Mountain or Pacific Time Zones. Apex to the rescue!



The Solution: I haven’t done much date manipulation in Apex, so I pulled out my trusty Apex Language Reference Manual. On page 182, the manual describes how you can use the “format” instance method to manipulate the date format: “format” takes a Java Class SimpleDateFormat string and the local time zone of the current user, and returns the datetime as a string. Perfect!

But what the heck is a “Java Class SimpleDateFormat” string? The document provided a link to the Java Sun website, where I learned all about date and time patterns, and using pattern letters to display full form vs. abbreviated form in datetime strings.

I switched over to my Sandbox, built a very simple Apex class to display the datetime in Microsoft (?) long date format:

public class MaintCalendar {

String LongDate = ' ';

// Init cLongDate with the current Datetime in long date format
public String getLongDate() {
Datetime cDT = System.now();
LongDate = cDT.format('EEEE, MMMM d, yyyy');
return LongDate;
}

}


The first line in my getlongDate method initializes the ‘cDT’ variable with the current datetime. The second line uses the “format” instance method to set a global string variable “LongDate”, using the following SimpleDateFormat string: ‘EEEE, MMMM d, YYYY’ The four letters indicate that the Day, Month and Year should be spelled out in full (non-abbreviated) form.

The code (and the VF page output) is displayed below.



Phew! Am I glad I figured that out. Every time I started working on the Calendar code, that ugly default date format in the {!Today()} function mocked me, telling me that I was making an ugly UI. Well, that’s enough code for this week … for some reason I now have a craving for orange creamsicles. Need to go find an ice cream truck.

5 comments:

  1. Cool. I suspect you can write a long formula to do the same thing (using CASE to map MONTH(today()) to month name for example), though that's a little laborious. Perhaps what you really want is the FORMAT function available in formulas... Hmmm - maybe put in a request on ideas.salesforce.com!

    ReplyDelete
  2. I thought about using CASE, and keeping the code entirely in the Visualforce page, but hit two snags with that:

    1.) I couldn't figure out how to map the day of the week, displaying "WEDNESDAY" rather than "WED".

    2.) I couldn't figure out how to get the displayed date in local time rather than GMT time.

    I do like the idea of putting the FORMAT function in formulas. I'll see if that Idea is already up on the IdeaExchange, if it's not I'll post it.

    ReplyDelete
  3. Interesting post. Out of curiosity, can the code handle users' locations? In other words, Will the class calculate the time appropriately for each user, allowing international support?

    ReplyDelete
  4. Great post.... How can it be tested ? in a test method?

    ReplyDelete
  5. Calling "getLongDate" in a test method would do it, though perhaps just calling the page might do it too?
    In any event, this is such a simple method that just calling explicitly would cover all the testing needed.
    Great post, JP!

    ReplyDelete