I spun up a Salesforce DX scratch org and could not reproduce this issue, copying and pasting the exact line from the question.
$ python3
>>> from simple_salesforce import Salesforce
>>> sf = Salesforce(session_id=SFDX_SESSION_ID, instance_url=SCRATCH_URL)
>>> sf.query('SELECT Id FROM Opportunity')
OrderedDict([('totalSize', 0), ('done', True), ('records', [])])
>>> sf.Opportunity.create({'CloseDate' : "2018-05-09", 'Amount' : 20.0, 'StageName' : 'Closed Won', 'Name' : 'FIRST LAST'})
OrderedDict([('id', '0061F000002v5DrQAI'), ('success', True), ('errors', [])])
>>> sf.query('SELECT CloseDate FROM Opportunity')
OrderedDict([('totalSize', 1), ('done', True), ('records', [OrderedDict([('attributes', OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v38.0/sobjects/Opportunity/0061F000002v5DrQAI')])), ('CloseDate', '2018-05-09')])])])
Given that you are also observing the issue in Workbench, I wonder if you have some code running on Opportunity insert that somehow generates this error as a confusing side-effect. However, based on the current simple_salesforce
source tree, this particular response is only generated on an actual 400 error code from the server.
The date format, at any rate, looks like it is probably not the true issue. I have an internal ETL tool written in Python with simple_salesforce
that inserts thousands of records with dates in this format, and those work.
The place I get errors with simple_salesforce
and Date fields is an empty string ('') read from a CSV in a Date column. This yields
Cannot deserialize instance of date from VALUE_STRING value or request may be missing a required field
as do other obvious failures in date formatting. That suggests to me, again, that the source of this issue is unique to your org in some fashion.
Do you have automation in place on Opportunity that could in any way manipulate a date field (even one other than Close Date)? Is your org in a non-United States locale? Is there any possibility that the data you're copying and pasting on your local machine includes control or nonprinting characters?
So, it sounds like you are trying to do the following:
- Retrieve a
String
that represents time in PST timezone
- Convert that time to PST DateTime
- Find the GMT representation of the PST
DateTime
In order to convert the String
that represents time in PST, you need to create a DateTime
instance in GMT and then use the format()
method to convert to PST.
Datetime pstDateTime = Datetime.valueOf(Datetime.newInstanceGMT(System.today(), <Time>).format('yyyy-MM-dd HH:mm:ss', 'PST'));
Once you have the pstDateTime
, you can then create another instance of DateTime
for GMT by manually constructing this instance using the pstDateTime
attributes.
Datetime gmtDateTime = Datetime.newInstanceGMT(pstDateTime.year(), pstDateTime.month(), pstDateTime.day(), pstDateTime.hour(), pstDateTime.minute(), pstDateTime.second());
Using the code you have provided in your question and my code to resolve your issue, the following should work.
String timeStr = '15:00';
String defaultTime = '00:00';
String[] ct =
(timeStr != null) ?
timeStr.split(':') :
defaultTime.split(':');
Time t = Time.newInstance(Integer.valueOf(ct[0]), Integer.valueOf(ct[1]), 0, 0);
Datetime pstDateTime = Datetime.valueOf(Datetime.newInstanceGMT(System.today(), <Time>).format('yyyy-MM-dd HH:mm:ss', 'PST'));
Datetime gmtDateTime = Datetime.newInstanceGMT(pstDateTime.year(), pstDateTime.month(), pstDateTime.day(), pstDateTime.hour(), pstDateTime.minute(), pstDateTime.second());
Best Answer
Try this:
Reason: You are type casting Date to DateTime. Date does not have Time component so formatting behave incorrectly.