2

Apparently if I want to format a date to my own format ie. 1 June 2016 10:44 am I can only do this with outputText but output text does not respect the users time zone so everything is GMT. If I use outputField it automatically converts it to the users time zone but I have no control over the format it displays it in. Does someone know how to get my custom format to display in the users time zone? I don't care which I use I just want to show it my way in the proper time zone

This respects users time zone but I cannot control formatting

<apex:outputField value="{!c.CreatedDate}"/>

or This does not respect users time zone but I can control formatting

<apex:outputText value="{0,date,dd MMM YYYY h:mm a}">
  <apex:param value="{c.CreatedDate}"/>
</apex:outputText>

This method is called from the controller when page is called and populates the variable csComments with records

public void ShowComments() {
  disp = true;
  RetrieveAcctInfo();
  caseNo = System.currentPagereference().getParameters().get('cn');
  System.debug('Case No: ' + caseNo);
  cd = [select id, AccountId, Priority from Case where CaseNumber=:caseNo];
  if (acctid != cd.AccountId) { disp = false; errMsg = 'Access Restricted'; } 
  else {
    csComments = [select Comment__c, CreatedDate from CSPComments__c where CaseCom__c=:cd.id ORDER BY CreatedDate DESC];
    ccCount = csComments.size();
  }
  initpri = new List<SelectOption>();  
  initpri.add(new SelectOption('None',' -- Select Priority --', true));
  initpri.add(new SelectOption('Level 1','1 - System Down'));
  initpri.add(new SelectOption('Level 2','2 - Funtioning with Errors'));
  initpri.add(new SelectOption('Level 3','3 - System Issue'));
  initpri.add(new SelectOption('Level 4','4 - Non Critical Issue'));
  inpri = cd.Priority;
  curpri = inpri;
}

This is the part of the page that is showing the results. The manager wants my date to be in the approved style of 1 June 2016 11:26 am

  <apex:pageBlock id="cl" rendered="{!disp}">
   <!-- Retrieved {!ccCount} comments<br />  -->
    <table><tr><th>Date/Time</th><th>Comment</th></tr>  
    <apex:repeat value="{!csComments}" var="c">
        <tr style="padding:4px 0px 4px 0px">
          <td padding-right="4px">
            <!-- <apex:outputText value="{0,date,d MMM YYYY h:mm a}"><apex:param value="{!c.CreatedDate}"/></apex:outputText>  -->
              <apex:outputField value="{!c.CreatedDate}" />
            </td>
          <td><textarea class="dtarea" rows="4" cols="60" disabled="true">{!c.Comment__c}</textarea></td>
        </tr>
    </apex:repeat>
    </table>  
  </apex:pageBlock>
5
  • 1
    Just a try, can you add a space in value of apex:param like following, {<apex:outputText value="{0,date,dd MMM YYYY h:mm a}"> <apex:param value=" {c.CreatedDate}"/> </apex:outputText>}
    – Anurag
    Commented Jun 1, 2016 at 15:00
  • 1
    If you have a controller attached to the visualforce page, you can use DateTime.Format(...) and a getter such as public String FormattedDate { get { return SomeDateTime.Format(...); } }. Commented Jun 1, 2016 at 15:08
  • 1
    When I put a space before the param value the console throws an error and won't let me save it
    – Ohmicron
    Commented Jun 1, 2016 at 15:09
  • I would do that @battery.cord if it wasn't a list of records from a query being displayed on the vf page. Have no idea how when stepping through the list of records and 'get' a formatted value for just one field of the returned results
    – Ohmicron
    Commented Jun 1, 2016 at 15:10
  • Is there a controller attached to the page? If so, it would be helpful to edit that into the question, so others might be able to provide alternative solutions to your problem. Commented Jun 1, 2016 at 15:15

2 Answers 2

2

Create a component that you can embed in your code, which will format things for you (you will format the date properly in the controller).

You can use this component in lieu of apex:outputText

Example (You may need to adjust your time format)

<c:FormattedDateTime datetimeValue="{!c.createdDate}" datetimeFormat="yyyy-MM-dd h:mm a" />

Component

<apex:component access="global" controller="FormattedDateTimeController">{!FormattedDatetime}
    <apex:attribute assignTo="{!valueToFormat}" description="The DateTime value to be rendered" name="datetimeValue" type="DateTime"></apex:attribute>
    <apex:attribute assignTo="{!definedFormat}" description="The optional format to use for the DateTime value to be rendered" name="datetimeFormat" type="String"></apex:attribute>
</apex:component>

Controller

public class FormattedDateTimeController {
    public DateTime valueToFormat { get; set; } //property that reads the datetime value from component attribute tag
    public String definedFormat { get; set;} //property that reads the string value from component attribute tag

    public String getFormattedDatetime() {
        if (valueToFormat == null) {
                return ''; 
        } else { 
            if (definedFormat == null) {
                return valueToFormat.format(); //return the full date/time in user's locale and time zone
            } else { 
                return valueToFormat.format(definedFormat);  //Specify Time zone like IST,CST
            }
        }
    }
}
4
  • great idea as it would be available to any page but the createddate field in my results seems to get converted to a string so I can create the controller and the component but when I go to call the new component with my query results and feed it c.CreatedDate it complains that it expects a datetime but is seeing a String. What is up with the modelMap variable? I'm not sure what you are doing there
    – Ohmicron
    Commented Jun 1, 2016 at 16:23
  • ModelMap was the name of my variable.... simply pass any DateTime field. I just changed my example to read c.createddate... but you must ensure that it is of DT type. Commented Jun 1, 2016 at 16:25
  • 1
    Thanks Sebastian the string it passes when it comes from a query is ugly and not easily converted to a DateTime object but I enhanced the custom component to let me pass it the string results from the query and create a DateTime object from that then format it properly. A little more code work but the custom component can easily be used over and over
    – Ohmicron
    Commented Jun 1, 2016 at 19:08
  • Glad it worked! Commented Jun 1, 2016 at 19:13
0

I would handle this inside the controller using a apex Map. First I'd create the below map:

public Map<Id, String> dateCommentCreated { get; set; }

And then make a small modification to the controller's method:

public void ShowComments() {
  disp = true;
  RetrieveAcctInfo();
  caseNo = System.currentPagereference().getParameters().get('cn');
  System.debug('Case No: ' + caseNo);
  cd = [select id, AccountId, Priority from Case where CaseNumber=:caseNo];
  if (acctid != cd.AccountId) {
       disp = false; 
       errMsg = 'Access Restricted'; 
  } else {
    csComments = [select Comment__c, CreatedDate from CSPComments__c where CaseCom__c=:cd.id ORDER BY CreatedDate DESC];

    dateCommentCreated = new Map<Id, String>();

    for (CSPComments__c comment:csComments) {
        dateCommentCreated.put(comment.Id, comment.CreatedDate.format('dd MMM YYYY h:mm a'));
    }

    ccCount = csComments.size();
  }

  initpri = new List<SelectOption>();  
  initpri.add(new SelectOption('None',' -- Select Priority --', true));
  initpri.add(new SelectOption('Level 1','1 - System Down'));
  initpri.add(new SelectOption('Level 2','2 - Funtioning with Errors'));
  initpri.add(new SelectOption('Level 3','3 - System Issue'));
  initpri.add(new SelectOption('Level 4','4 - Non Critical Issue'));
  inpri = cd.Priority;
  curpri = inpri;
}

You should be able to access these values inside of your visualforce with the following line:

<apex:outputField value="{!dateCommentCreated[c.Id]}" />

Ideally, you would be able to skip this entire process, and specify a timezone inside visualforce. Hopefully, someone else posts a solution which allows you to just use visualforce tags to get the correct formatting. Additionally, if the format(...) method fails to detect the correct timezone automatically, you should be able to use this format(..., timezone) to specifiy an exact timezone.


As an alternative solution, if you are using a wrapper class, you can control the formatting using a get method, or a formatting method attached to the class.

public class DemoWrapper {

    private sObject Record { get; set; } 

    public String CreatedDate {
        get {
            return Record.CreatedDate.format('dd MMM YYYY h:mm a'); 
        }
    }

    public DemoWrapper(sObject Record) {
        this.Record = Record; 
    }

}

Disclamer: Second answer was written since I found this answer while googling for solution, and wasn't happy with either solution presented, this is mostly so when I find this again, I have more options.

You must log in to answer this question.

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