This is what i was able to find out:
The dates in ListItemAllFields seem to always be in the local time rather than UTC, as you mentioned. I am not sure WHY this happens, but at least seems to happen consistently. If for some reason it doesn't for you, you can tell if the time is UTC or not with the Z at the end of the datestring - if it's here, it's UTC, otherwhise it isn't.
For your second question, I wasn't able to find anything like that. However, there are a few options to work around this:
- Use the LocalTimeToUTC endpoint
As the name suggests, this endpoint converts a date string to UTC based on the configured local date of the site.
This would be the easiest way if you just want to convert one date. If you need to do this a lot though, it would probably easier to use the second option.
- Get the timezone and convert it yourself
With a call to /_api/web/RegionalSettings/TimeZone you can fetch the timezone information of the site:
"Description": "(UTC-08:00) Pacific Time (US and Canada)",
If you add up all the biases in that response and add those minutes to the dates you get from ListItemAllFields, you get the time in UTC. This way you only need to do one call per site you want to get the metadata from, rather than one call per item.
Even though that doesn't really fix the issue itself of getting non-UTC in the responses (and it's 8 months late 😔), I hope this helps.