Fixing Times on EXIF

I’ve been working on a patch for WordPress that involves fixing the incorrectly stored timestamp stored as part of WordPress image metadata. I already do something like this in my Simple Location plugin, but I’ve found a way that works more simply.

To summarize the issue, there are multiple datetime properties stored in your photos. The creation time of the file(DateTime), the time the image was created(DateTimeOriginal), and the time it was digitized(DateTimeDigitized. There are two separate properties for the GPS time and date.

The problem being that the GPS time and date, which may not reflect when the picture was taken, but the last GPS lock, is in UTC, but the rest have no defined timezone. With photos taken on a cell phone, if you have GPS time and date, you also have location, which can be used to figure out timezone as well.

Offset fields for the three datetime stamps mentioned were introduced in EXIF version 2.31, which came out in July of 2016. PHP returns these with its exif_read_data function as ‘UndefinedTag:0x9010’, ‘UndefinedTag:0x9011’, ‘UndefinedTag:0x9012’, reflecting DateTime, DateTimeOriginal, and DateTimeDigitized respectively.

I don’t support these, and just learned about them, and intended to support them…until I read EXIF version 2.32, which just came out last year and no one is using yet. They are retiring all of those offset formats they introduced in 2.32 and switching all their date properties to ISO8601. They are also changing GPS Coordinate storage, if you use that.

So any code has to check the EXIF version, and if 0231, check the offset. If 0232, use just the properties, and if less than 0231, try to derive from the GPS location or timestamp.


function exif_gpsdatetime( $datestamp, $timestamp ) {
return new DateTimeImmutable(
$datestamp . ' ' . sprintf( '%02d:%02d:%02d', (int) $timestamp[0], (int) $timestamp[1], (int) $timestamp[2] ),
new DateTimeZone( 'UTC' )
);
}

function derive_exif_timezone( $datetime, $gmtdatetime ) {
$seconds = $datetime->getTimestamp() - $gmtdatetime->getTimestamp();
return new DateTimeZone( timezone_name_from_abbr( '', $seconds, 0 ) );
}

Here are the two functions that I’m using to calculate timezone offset without using geo coordinates. You can also use a timezone lookup database for the location, but this adds another dependency.

If you want to go solely using built-in PHP functions, you can get the datetime stamp(whichever of the properties you are using), set to assume it is UTC, figure out the difference between the two times, and use that to calculate a timezone, which you apply to the original.

WordPress takes the digitized property and converts it to a timestamp using strotime, which is usually an inaccurate timestamp and therefore useless. I am trying to get this fixed.

David Shanske

My day job is in training for an airline. I also develop Indieweb WordPress plugins so that others can take control of their online identity.

Leave a Reply

Your email address will not be published. Required fields are marked *