@Howdy_McGee is on the right track in his comment: by the time transition_post_status is fired, the post has already been updated (i.e., written to the db).
What you need to do is hook into wp_insert_post_data, instead of transition_post_status
, as follows:
add_filter ('wp_insert_post_data', 'mycpt_keep_pending_date_on_publishing', 10, 2) ;
function
mycpt_keep_pending_date_on_publishing ($data, $postarr)
{
if ($data['post_type'] != 'mycpt') {
return ($data) ;
}
// this check amounts to the same thing as transition_post_status(private, pending)
if ('private' != $data['post_status'] || 'pending' != $postarr['original_post_status']) {
return ($data) ;
}
$pending_datetime = get_post_field ('post_date', $data['ID'], 'raw') ;
$data['post_date'] = $pending_datetime ;
$data['post_date_gmt'] = get_gmt_from_date ($pending_datetime) ;
return ($data) ;
}
Note: I used the same function name as you did, but the body of that function is different.