drewnoakes / metadata-extractor

Extracts Exif, IPTC, XMP, ICC and other metadata from image, video and audio files
Apache License 2.0
2.54k stars 475 forks source link

TimeZone for FileSystemDirectory #603

Closed ChrLipp closed 1 year ago

ChrLipp commented 1 year ago

I am parsing an iPhone photo. The creation Date is available multiple times. I am accessing the date with

        .getDate(FileSystemDirectory.TAG_XXX, TimeZone.getDefault())

and I am receiving

- Exif IFD0 Directory (10 tags).name
  - Exif IFD0, Date/Time, 2018:01:20 19:20:09
    Gives "Sat Jan 20 19:20:09 CET 2018"
- Exif SubIFD Directory (34 tags).name
  - Exif SubIFD, Date/Time Original, 2018:01:20 19:20:09
    Gives "Sat Jan 20 19:20:09 CET 2018"
- File Directory (3 tags).name
  - File, File Modified Date, Sa. Jän. 20 18:20:09 +01:00 2018
    Gives "Sat Jan 20 18:20:09 CET 2018"

In the last case the function getData is not able to resolve the time zone information ("+1:00"), which I do believe is a bug. I am using the current version (2.18.0).

But when I look at the file creation and modified date it is 18:20:09. To be honest, I do not understand which one is right or wrong.

drewnoakes commented 1 year ago

The first two are timestamps from the file's embedded metadata. They are most likely to represent when the image was created.

The third is the timestamp of the file on the file system, external to the file. Was the file copied to a local disk at that point in time?

ChrLipp commented 1 year ago

No, this happend some months later. The file system timestamp should be identically. But I did investigate further, in my opinion theses are iPhone software errors and do not belong to your library. The only thing that keeps left is that the time zone entry (the offset +01:00) is not resolved correctly:

drewnoakes commented 1 year ago

I don't think file systems store time zones in their metadata about files. We'll just be reporting the value in local time.

There doesn't seem to be any action for us to take here, so I'll close this out. Let me know if missed anything.

ChrLipp commented 1 year ago

Your library, your decision. When I use a library, I file issues when I find bugs to give feedback and say "thank you" for your work.

With this code

    ImageMetadataReader
        .readMetadata(file)
        .directories
        .forEach { directory ->
            log.info { "- $directory.name" }
            for (tag in directory.tags) {
                log.info("  - ${directory.getName()}, ${tag.getTagName()}, ${tag.getDescription()}")
            }
        }

I got

so the offset is obviously stored in the meta data. With this code

    val directory = ImageMetadataReader
        .readMetadata(file)
        .getFirstDirectoryOfType(FileSystemDirectory::class.java)
        ?: return null
    val date = directory
        .getDate(FileSystemDirectory.TAG_FILE_MODIFIED_DATE, TimeZone.getDefault())
        ?: return null

I got

Gives "Sat Jan 20 18:20:09 CET 2018"

So the translation is definitly wrong. But again, I can deal with it, no issue. Just wanted to give feedback. Thanks for your work, your library saved me a lot of work.

drewnoakes commented 1 year ago

so the offset is obviously stored in the meta data

The stored metadata comes from the file system. When the library reads it, it interprets it as local time, and presents it to you. Another alternative would be to display it to you in UTC, but that's generally not so friendly.

In your second example, you're calling getDate to get the Date object, which is then formatted using a different presentation. My guess is that you're in CET which is UTC+1. If so, I don't see any error in the above. Am I missing something?

Thanks for your work, your library saved me a lot of work.

You're welcome. Glad it has been helpful to you.

ChrLipp commented 1 year ago

Understood. I wasn't aware that File Directory is not stored in meta data but is directly read from the file system - my fault. This explains why the time zone differs from the other two:

So the reason for the difference is in the iPhone Photo app. Thanks for explaining!