Should the WordPress scheduler use datetime-local?
There's a brilliant post by WordPress about how they've optimised some of the backend code to make it more efficient. So here's a suggestion for something else which can be optimised.
If you want to schedule a blog post to be published later, you have to use this WordPress control:
I find it mildly annoying. I don't get why part of it is a dropdown. And the number fields don't pop up my phone's number keypad. And I have to look at a different calendar if I want to schedule something for a Saturday.
But how efficient is it on the back-end?
Every time you save, schedule, or edit a blogpost - this is what is POSTed to the server:
mm=09
jj=04
aa=2023
hh=12
mn=34
ss=20
Interestingly, the "seconds" are from a hidden input field! <input type="hidden" id="ss" name="ss" value="18" />
WordPress can't rely on a front-end control for validation. So here's the code that goes into checking whether a POSTed date is valid:
PHP$aa = $post_data['aa'];
$mm = $post_data['mm'];
$jj = $post_data['jj'];
$hh = $post_data['hh'];
$mn = $post_data['mn'];
$ss = $post_data['ss'];
$aa = ( $aa <= 0 ) ? gmdate( 'Y' ) : $aa;
$mm = ( $mm <= 0 ) ? gmdate( 'n' ) : $mm;
$jj = ( $jj > 31 ) ? 31 : $jj;
$jj = ( $jj <= 0 ) ? gmdate( 'j' ) : $jj;
$hh = ( $hh > 23 ) ? $hh - 24 : $hh;
$mn = ( $mn > 59 ) ? $mn - 60 : $mn;
$ss = ( $ss > 59 ) ? $ss - 60 : $ss;
$post_data['post_date'] = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $aa, $mm, $jj, $hh, $mn, $ss );
$valid_date = wp_checkdate( $mm, $jj, $aa, $post_data['post_date'] );
if ( ! $valid_date ) {
return new WP_Error( 'invalid_date', __( 'Invalid date.' ) );
}
$post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
That's quite complex. Luckily, there is an easier way.
There is a specific HTML input element for entering dates and times. You write <input type="datetime-local">
and you get:
That will show a browser's native datetime picker and it works on every browser. It works brilliantly on mobile and desktop. It makes it much easier for a user to select the date and time that they want.
When the element is submitted, it POSTs an ISO8601 / RFC 3339 string. Something like 2023-08-27T12:34
. This dramatically simplifies the back end code. That large complex function can now be reduced to either:
PHP$dateTime = $post_data['dateTime'];
if ( strtotime($dateTime) == false ) {
...
}
or
PHP$dateTime = DateTime::createFromFormat( "Y-m-d\TH:i", $post_data['dateTime'] );
if ( $dateTime == false ) {
...
}
I don't know if WordPress specifically needs to record the seconds something is scheduled for. If that is necessary, a random int can be zero padded and shoved on the end.
Performance
With something like this, you're always chasing marginal gains. Based on my very rough profiling, I expect the new function to be about twice as fast, albeit using about twice the memory. But we're talking fractions of seconds and hundreds of bytes.
Nevertheless, it all adds up!
It can't be that easy, right?
Well, probably not. There are several places where a date picker is used - so they'd all have to be changed.
I imagine there are several other things which expect to see jj, mm, dd etc posted. They'd either need to be updated, or a little front-end JS would have to be done.
And, as per the obligatory XKCD this will inevitably annoy someone.
But… it seems sensible, right? Use a native HTML control, a built-in PHP validator, and remove a bunch of custom code.
So, what do you think?
Morten Juhl-Johansen said on mstdn.dk:
@Edent It would appear to make good sense.
Dan Q says:
This has annoyed me for literally years. But I'm so ingrained into the ecosystem I don't even see it any more! I love the "new" input types like datetime-local and agree that they'd probably be a great idea for this control. For me it's not even about the efficiency: I just hate that I keep having to enter dates in month/day/year ordering!
Have you looked at the WordPress Core tickets list to see if it's been requested already? Although in my experience if you want something in WordPress it's often fastest to write it yourself (as a plugin if possible) so that people can try it out and so you can gauge interest first.
Carsten Bach said on dewp.space:
@Edent Yes, please.
Neil says:
If it's currently September and a UK based user is scheduling their post to publish in November, what timezone will that be in?
Will they be surprised if it actually publishes an hour after they expected it to? Conversely, earlier in the year, might a post appearing an hour earlier than expected cause issues, perhaps breaking an embargo?
What's the clear and simple UX for that?
@edent says:
Firstly, the current UI doesn't allow users to specify whether it is daylight savings time or not. In my experience, it always publishes in "local" time.
Secondly, my proposed new UI has an ISO8601 string sent to the server which is also local. There is no timezone or DST information sent. So, again, it will appear at the expected time.
You can try this yourself now. In the UK, the clocks go back at the end of October. So write a post now and schedule it for the start of November and see if it publishes when you expect it to.
Neil says:
Perhaps it should? Users won't think about this sort of thing and could be sad later. Even then, offering them a timezone isn't enough because some of them won't think to change it. Or won't know what 'UTC' means anyway.
"local" is a vague term... User's browser? server? database? If the browser doesn't send a Z(something) at the end of the date string and the server doesn't convert using the browser's locale, the server and database are going to store the given date in whatever their local (usually the OS but can be overridden) time is. Assuming the server and db are both fixed at UTC it'll publishing at that time UTC.
Something must be handling TZ otherwise using a BST browser now to schedule for 9am tomorrow would store a date of 9am server local time and so actually publish at 10am BST.
@edent says:
I'm not really sure what you're arguing about.
The current version of the UI doesn't specify a timezone. Neither does my proposed version. So there's no negative impact on users.
When a user sets up WordPress, they specify the timezone the blog is in. Mine is set to "London, UK".
WordPress knows what TZ the city is in. So when a user says "23:07 on December 25th" it will be local to the specified city. So the user doesn't need to specify a timezone. It will interpret any scheduled date as local to the blog. It doesn't matter where the user is, what time their browser thinks it is, or whether they're in a country with a different DST schedule. Time is always local to the blog's pre-set timezone.
I hope that clears things up for you.
Neil says:
Not arguing, just trying to understand how it works.
Yes, that does, thanks.
@edent says:
Sadly, this suggestion has been rejected. See https://core.trac.wordpress.org/ticket/61652#comment:8
More comments on Mastodon.