+ Start a Discussion
tengeltengel 

Output datetime in UTC format for VF email template

I have a custom object that has Start and End fields as datetime. I am trying to create a Visualforce email template that will be able to send an email with a .ics attachment that will use my object's Start/End fields.

I've got everything working except that my object's field values are getting output as GMT, not UTC, and the .ics format needs UTC. Here's what I've got in the template (PS, I've tried not wrapping my fields in the outputText tags, the result is the same):
DTSTART;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__Start__c}" />
DTEND;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__End__c}" />
Here is an example of what gets output in the resulting .ics file:
DTSTART;TZID="Eastern Standard Time":Mon Jul 06 17:00:00 GMT 2015
DTEND;TZID="Eastern Standard Time":Mon Jul 06 21:00:00 GMT 2015
How do I just get VF to output my fields in UTC? Isn't this how they are actually stored in the database, anyway??

Douglas AyersDouglas Ayers
Take a look at my markup for a visualforce page that builds .ics calendar entry (https://gist.github.com/DouglasCAyers/ada5a2a1708099f6ed7e). You'll notice some workarounds to get the date to format correctly so Outlook and other calendar systems understand the time correctlly.
Douglas AyersDouglas Ayers
Dangit, can't edit once comment posted... I wanted to point out the line you needed:

Note that we specify the timezone to be GMT (that tells the client program that reads the date that the value is specified in GMT and that the client program should adjust it appropriately for the locale of the end-user) then the outputText value uses a series of SUBSTITUTE commands to strip unecessary characters out.

In this example, $CurrentPage.parameters.start could be replaced by the formula {!TEXT(yourObject.yourDateTimeField)}
DTSTART;TZID=GMT:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE($CurrentPage.parameters.start,':',''),'-',''),' ','T')}"/>

tengeltengel
DouglasCAyers, thank you! I feel that I am really close, but something just ain't right. And I suspect it's some insane MS Outlook thing that I would never expect ANYONE to know the root of, but in case you are a super genius ;)    ..........

My test emails deliver just fine to services like Gmail. I receive the calendar request, can accept it, beautiful!

However, when the message is opened in an MS Outlook client (Outlook 2010, in this case), the message is delivered properly with the .ics attachment BUT the attachment is labeled "not supported calendar message.ics" (even though I've specified the filename as "meeting.ics"). Yet, when I open the attachment, it opens the MS Calendar to the correct date & time as specified in my Salesforce object fields. I did some googling, but the only consistent solution I see that addresses this has something to do with Lotus Notes recurring meetings, which doesn't apply in this case. Any chance my code below tips you off to anything???

This is the code in my VF template:
<messaging:attachment filename="meeting.ics" 
        renderAs="text/calendar; charset=UTF-8; method=REQUEST">
BEGIN:VCALENDAR
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP;TZID=GMT:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__Start__c),':',''),'-',''),' ','T')}"/>
UID:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__Start__c),':',''),'-',''),' ','T')}"/>
ATTENDEE;CN={!RelatedTo.evt__Email__c};RSVP=TRUE:mailto:{!RelatedTo.evt__Email__c}
STATUS:CONFIRMED
DESCRIPTION:Thank you for Registering for our Event!\n\nHere is a summary!\
    n\nYay!\n
DTSTART;TZID=GMT:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__Start__c),':',''),'-',''),' ','T')}"/>
DTEND;TZID=GMT:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__End__c),':',''),'-',''),' ','T')}"/>
LOCATION:{!RelatedTo.evt__Event__r.evt__Venue_Name__c} - {!RelatedTo.evt__Event__r.evt__Street__c}, {!RelatedTo.evt__Event__r.evt__City__c} {!RelatedTo.evt__Event__r.evt__State__c} {!RelatedTo.evt__Event__r.evt__Postal_Code__c}
ORGANIZER;CN="Test":mailto:test@lawleyinsurance.com
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=en-us:{!RelatedTo.evt__Event__r.Name}
TRANSP:OPAQUE
DESCRIPTION:{!RelatedTo.evt__Event__r.evt__Landing_Page_HTML__c}
END:VEVENT
END:VCALENDAR
</messaging:attachment>

This is how that code renders when delivered:
BEGIN:VCALENDAR
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP;TZID=GMT:20150706T170000Z
UID:20150706T170000Z
ATTENDEE;CN=tengelhardt@lawleyinsurance.com;RSVP=TRUE:mailto:tengelhardt@lawleyinsurance.com
STATUS:CONFIRMED
DESCRIPTION:Thank you for Registering for our Event!\n\nHere is a summary!\
    n\nYay!\n
DTSTART;TZID=GMT:20150706T170000Z
DTEND;TZID=GMT:20150706T210000Z
LOCATION:Statue of Liberty - , Liberty Island NY 10004
ORGANIZER;CN="Test":mailto:test@lawleyinsurance.com
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=en-us:Sample Quick Event
TRANSP:OPAQUE
DESCRIPTION:&lt;p&gt;Sample landing page content&lt;/p&gt;
END:VEVENT
END:VCALENDAR