I have seen quite a few questions and answers regarding the conversion and display of a JSON serialized DateTime
field in JavaScript and the effects of UTC on that data related to the user's locale but I have yet to be able to find a solution to the issue I'm facing here.
I am using @RemoteAction
methods to expose a custom Apex Type to the page. When performing the retrieve operation, the DateTime
members on the class are serialized into the unix epoch format.
{
name: "Item Name",
theDate: 1440797362525
}
However, when performing a commit back to the controller with this exact same data, the unix epoch format is not able to be deserialized back into the concrete type and it throws an exception.
Visualforce Remoting Exception: Unable to convert date '1440797362525' to Apex type Datetime.
What is the correct way to implement this very simple pattern? Am I just doing it wrong? This seems like "JS Remoting: 101" and it shocks me that it does not work.
Update: apparently this is only an issue with a concrete type on my own class. Tried the same code with the Contact
sObject, no exception thrown.
Controller
public with sharing class DateTimeSerializationController {
public class MyItem {
public String name { get; set; }
public DateTime theDate { get; set; }
}
@RemoteAction
public static MyItem fetchTheItem() {
MyItem item = new MyItem();
item.name = 'Item Name';
item.theDate = DateTime.now();
return item;
}
@RemoteAction
public static MyItem storeTheItem(MyItem item) {
// DML or something similar could happen here
system.debug(item);
return item;
}
@RemoteAction
public static Contact fetchTheContact() {
Contact item = new Contact();
item.FirstName = 'Joe';
item.LastName = 'Bob';
item.My_Date__c = DateTime.now();
return item;
}
@RemoteAction
public static Contact storeTheContact(Contact item) {
// DML or something similar could happen here
system.debug(item);
return item;
}
}
VF Page
<apex:page controller="DateTimeSerializationController">
<script>
window.myApp = window.myApp || {};
window.myApp.fetchItem = function() {
Visualforce.remoting.Manager.invokeAction(
'DateTimeSerializationController.fetchTheItem',
function(result, event){
if (event.status) {
console.log(result);
myApp.myItem = result;
} else {
console.log(event.message);
}
},
{escape: true}
);
}
window.myApp.storeItem = function() {
Visualforce.remoting.Manager.invokeAction(
'DateTimeSerializationController.storeTheItem',
myApp.myItem,
function(result, event){
if (event.status) {
console.log(result);
} else {
console.log(event.message);
}
},
{escape: true}
);
}
window.myApp.fetchContact = function() {
Visualforce.remoting.Manager.invokeAction(
'DateTimeSerializationController.fetchTheContact',
function(result, event){
if (event.status) {
console.log(result);
myApp.myContact = result;
} else {
console.log(event.message);
}
},
{escape: true}
);
}
window.myApp.storeContact = function() {
Visualforce.remoting.Manager.invokeAction(
'DateTimeSerializationController.storeTheContact',
myApp.myContact,
function(result, event){
if (event.status) {
console.log(result);
} else {
console.log(event.message);
}
},
{escape: true}
);
}
</script>
<p>Open the browser console and then click the buttons.</p>
<button onclick="myApp.fetchItem();">Fetch Item</button>
<button onclick="myApp.storeItem();">Store Item</button>
<button onclick="myApp.fetchContact();">Fetch Contact</button>
<button onclick="myApp.storeContact();">Store Contact</button>
</apex:page>