GA Hiker

New Member
Joined
Sep 29, 2018
Messages
8
After a trip, I transferred my photos/videos from my SD camera memory card to my PC using copy/paste in Windows Explorer. The Media created date/time on the PC MP4 files are 4 hours earlier that they should be. When the Date modified is "9/24/2018 2:52 PM" the Media created date/time shows "9/24/2018 10:52 AM". For JPG files Date taken and Date modified are equal. When I try to correct the Media created date/time I am only able to change the date, not the time. Why is this happening? How can I correct it?
 


On a recent trip, my husband and I each took photos/videos which we now want to merge. Unfortunately, the times on our cameras were set an hour apart, making it impossible to sort our photos together by date/time. Is there a way to change the date/times of my 1000+ photos?
 


Some explanations would that you were in a different time zone, or the device that created the pictures/videos time was off.

You may need to use Powershell to change the time like so

1538246656308.webp
 


Threads merged since it's the same. Let me know the requirements for the time change and I can help write some Powershell code to correct the time.
 


Thank you for your reply. All of the photos/videos were taken in the same time zone. My camera's destination time was set to five (5) hours earlier than my home time zone (not 4). I can think of no reason why the videos are given a time, in only one of the date/time fields, that is 4 hours earlier than its other date/times and all the date/times in the photos. It certainly seems like a bug.

Although I am a retired software developer, I only learned of the existence of Powershell a couple days ago when Googling for solutions to my problem. In the past, on DOS systems, I have written many .bat files to accomplish a variety of tasks. While I follow what you have done, without a Powershell manual I don't know how, for each of a group of files, to retrieve the date/time needing change, adjust it, and replace it.
 


Threads merged since it's the same. Let me know the requirements for the time change and I can help write some Powershell code to correct the time.
I wrote my previous reply before I saw this message. What I need to do is, for each of my MP4 files, change the existing "Media created" date/time to 4 hours earlier.

After that, I assume I will be able to figure out how to modify that code to change date/times in all my photo/video files from this trip to 1 hour earlier. Embarrassed to explain that my camera was set to 5 hours earlier than home when it should have been set to 6 hours earlier. I need to correct that in order to merge my photos/videos with my husband's. His camera was correctly set to 6 hours earlier.

Thank you so much.
 


So to be clear you need to set the creation time to 1 hour earlier on all the files?
 


If you only need to set the the time back 1 hour this should do it. Open a powershell prompt and copy the following code and hit enter. That will load this function in the current Powershell console. Then type Set-Filetime -FilePath "C:\Path\To\Root\Directory\Of\The\Pictures" and it will set the creation time back 1 hour.

Code:
Function Set-FileTime
{
    Param
    (
        [String]$FilePath
    )

    $Files = Get-ChildItem -Path $FilePath -Recurse

    Foreach($File in $Files)
    {
        $CreationTime = Get-ItemPropertyValue -Path $File.FullName -Name "CreationTime"
        $NewCreationTime = $CreationTime.AddHours(-1)
        Set-ItemProperty -Path $File.FullName -Name "CreationTime" -Value $NewCreationTime
    }
}
 


Can that code be put into a "batch" file? If so, what is the file extension and how do I execute it? Thanks.
 


That code alone, no thats just a function, but you can add the line to execute it at the bottom Set-Filetime -FilePath "C:\Path\To\Root\Directory\Of\The\Pictures"

Then save it as a .ps1 file. This won't execute though because Powershell relies on the execution policy which my default blocks scripts from running. You can set the execution policy with Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Unrestricted then you can run Powershell scripts.
 


I did exactly what you said. I opened a powershell prompt, I pasted your code to define the function and pressed enter. Then I typed:
"Set-Filetime -FilePath "C:\Users\Myname\Desktop\Testfiles"
I had 3 JPG files in the Testfiles folder. None of the times in those files changed -- not Date taken, Date created, or Date modified. I also tried it with an MP4 file -- nada. What I need to do is change the Date taken time in the JPG files and the Media created time in MP4 files. I can't believe this is such a challenge.

I also downloaded Bulk File Changer which seemed promising but didn't work either. Looks like it can change the time on a group of files but they all end up with the same time.
 


Might be a different field then. Looks like there is metadata field called DateTaken. This field isn't easy to update programmtically
 


Whew that was a bit of research and testing. This function should work.

*NOTE* I'd recommend testing on a copy to validate it works.
I also only wrote it for JPEG files, I believe it would have to be somewhat duplicated to work with other formats

After he function is loaded. Set-DateTaken -Directory "C:\Root\Of\Pictures"

Code:
Function Set-DateTaken
{
    
    [System.Reflection.Assembly]::LoadWithPartialName("PresentationCore")
    [System.Reflection.Assembly]::LoadWithPartialName("WindowsBase")
    [System.Reflection.Assembly]::LoadWithPartialName("System.Xaml")

    Param
    (
        [Parameter(Mandatory=$true)][String]$Directory
    )

    If(-not(Test-Path -Path $Directory))
    { exit }

    $Files = Get-ChildItem -Path $Directory -Recurse -Include "*.jpg","*.jpeg"

    Foreach($File in $Files)
    {
        $SourcePath = $File.FullName.Replace(".jpeg",".jpg")
        $DestinationPath = $File.FullName.Replace(".jpg","-new.jpg")
        [System.Windows.Media.Imaging.BitmapFrame]$Frame = $null

        $InputStream = [System.IO.File]::Open($SourcePath,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)
        $Decode = [System.Windows.Media.Imaging.JpegBitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)

        $Frame = $Decode.Frames[0]
        $MetaData = $Frame.Metadata.Clone()
        $DateTaken = $MetaData.DateTaken
        $NewDate = [DateTime]$DateTaken
        $NewDataTaken = $NewDate.AddHours(-1)
        $MetaData.DateTaken = $NewDataTaken


        $Encoder = New-Object System.Windows.Media.Imaging.JpegBitmapEncoder
        $Encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($Frame,$Frame.Thumbnail,$MetaData,$Frame.ColorContexts))


        $OutputStream = [System.IO.File]::Open($DestinationPath,[System.IO.FileMode]::Create,[System.IO.FileAccess]::ReadWrite)
        $Encoder.Save($OutputStream)

        $InputStream.Close()
        $OutputStream.Close()

        Remove-item $SourcePath
        Rename-Item $DestinationPath -NewName $SourcePath
    }
}
 


Ok so I figured because I'm kind of crazy I'd make it better... :) I've added a bunch of picture file types. It will handle jpg,bmp,gif,tiff,png and wmp now. It also has you specify the time increment and amount. To set it back seconds,minutes,hours etc supply it a negative value.

Example to set all the images "DateTaken" back 1 hour for "C:\Users\User\Pictures\Test", you type the following after loading the function.
Set-DateTaken -Directory "C:\Users\User\Pictures\Test" -TimeType Hours -Amount -1

New Code
Code:
Function Set-DateTaken
{
    [CmdletBinding()]

    Param
    (
        [Parameter(Mandatory=$true)][String]$Directory,
        [Parameter(Mandatory=$true)][ValidateSet("Seconds","Minutes","Hours","Days")][String]$TimeType,
        [int]$Amount=0
    )
    [System.Reflection.Assembly]::LoadWithPartialName("PresentationCore")
    [System.Reflection.Assembly]::LoadWithPartialName("WindowsBase")
    [System.Reflection.Assembly]::LoadWithPartialName("System.Xaml")

    If(-not(Test-Path -Path $Directory))
    {
        Write-Verbose "$Directory was not found, exiting..."
        exit
    }
    Else
    {
        Write-Verbose "$Directory found, proceeding..."
    }

    Write-Verbose "Grabing all image files from $Directory..."
    $Files = Get-ChildItem -Path $Directory -Recurse -Include "*.jpg","*.jpeg","*.bmp","*.dib","*.gif","*.tff","*.tif","*.wmp","*.png"

    Foreach($File in $Files)
    {
        $SourcePath = $File.FullName
        Write-Verbose "$($File.FullName) source path set to $SourcePath"
        $DestinationPath = $File.FullName.Replace($File.Extension,"-new$($File.Extension)")
        Write-Verbose "$($File.FullName) destination path set to $DestinationPath"
        [System.Windows.Media.Imaging.BitmapFrame]$Frame = $null

        Write-Verbose "Opeing IO stream to $File.Name for reading"
        $InputStream = [System.IO.File]::Open($SourcePath,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)

        If($File.Extension -match "\.jp(|e)g")
        {
            Write-Verbose "Decoder is set to JPG based on file extension"
            $Decode = [System.Windows.Media.Imaging.JpegBitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)
        }
        ElseIf($File.Extension -match "(\.bmp|\.dib)")
        {
            Write-Verbose "Decoder is set to BMP based on file extension"
            $Decode = [System.Windows.Media.Imaging.BitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)
        }
        ElseIf($File.Extension -match "(\.tiff|\.tif)")
        {
            Write-Verbose "Decoder is set to TIFF based on file extension"
            $Decode = [System.Windows.Media.Imaging.TiffBitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)
        }
        ElseIf($File.Extension -match "\.wmp")
        {
            Write-Verbose "Decoder is set to WMP based on file extension"
            $Decode = [System.Windows.Media.Imaging.WmpBitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)
        }
        ElseIf($File.Extension -match "\.png")
        {
            Write-Verbose "Decoder is set to PNG based on file extension"
            $Decode = [System.Windows.Media.Imaging.PNGBitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)
        }
        ElseIf($File.Extension -match "\.gif")
        {
            Write-Verbose "Decoder is set to GIF based on file extension"
            $Decode = [System.Windows.Media.Imaging.GIFBitmapDecoder]::Create($InputStream,[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,[System.Windows.Media.Imaging.BitmapCacheOption]::None)
        }

       
        $Frame = $Decode.Frames[0]
        $MetaData = $Frame.Metadata.Clone()

        <#
            Add new parameters in appropriate format for each meta dat tag
            Research all meta data fields

            Manipulate each meta data tag as needed
        #>
        $DateTaken = $MetaData.DateTaken
        If($DateTaken -eq $null)
        {
            $DateTaken = $File.CreationTime.ToString()
        }
        $NewDate = [DateTime]$DateTaken

                Switch ($TimeType)
        {
            "Seconds" { $NewDataTaken = $NewDate.AddSeconds($Amount); Break }
            "Minutes" { $NewDataTaken = $NewDate.AddMinutes($Amount); Break }
            "Hours" { $NewDataTaken = $NewDate.AddHours($Amount); Break }
            "Days" { $NewDataTaken = $NewDate.AddDays($Amount); Break }
        }
       
        $MetaData.DateTaken = $NewDataTaken

        Write-Verbose "Date Taken is now $NewDataTaken"

        If($File.Extension -match "\.jp(|e)g")
        {
            Write-Verbose "Encoder is set to JPG based on file extension"
            $Encoder = New-Object System.Windows.Media.Imaging.JpegBitmapEncoder
        }
        ElseIf($File.Extension -match "(\.bmp|\.dib)")
        {
            Write-Verbose "Encoder is set to BMP based on file extension"
            $Encoder = New-Object System.Windows.Media.Imaging.BitmapEncoder
        }
        ElseIf($File.Extension -match "(\.tiff|\.tif)")
        {
            Write-Verbose "Encoder is set to TIFF based on file extension"
            $Encoder = New-Object System.Windows.Media.Imaging.TiffBitmapEncoder
        }
        ElseIf($File.Extension -match "\.wmp")
        {
            Write-Verbose "Encoder is set to WMP based on file extension"
            $Encoder = New-Object System.Windows.Media.Imaging.WmpBitmapEncoder
        }
        ElseIf($File.Extension -match "\.png")
        {
            Write-Verbose "Encoder is set to PNG based on file extension"
            $Encoder = New-Object System.Windows.Media.Imaging.PngBitmapEncoder
        }
        ElseIf($File.Extension -match "\.gif")
        {
            Write-Verbose "Encoder is set to GIF based on file extension"
            $Encoder = New-Object System.Windows.Media.Imaging.GifBitmapEncoder
        }
       
        Write-Verbose "Encoding new image file for $($File.Name)"
        $Encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($Frame,$Frame.Thumbnail,$MetaData,$Frame.ColorContexts))

        Write-Verbose "Creating new file for $($File.Name)"
        $OutputStream = [System.IO.File]::Open($DestinationPath,[System.IO.FileMode]::Create,[System.IO.FileAccess]::ReadWrite)

        Write-Verbose "Saving new file data for $($File.Name)"
        $Encoder.Save($OutputStream)


        Write-Verbose "Cleaing up streams and old file for $($File.Name)"
        $InputStream.Close()
        $OutputStream.Close()

        Remove-item $SourcePath
        Rename-Item $DestinationPath -NewName $SourcePath
    }
}
 


WOW!!! I cannot believe you have put this much time and effort into this to help a stranger. I can't thank you enough. Yes, it worked! Turns out I was confused about the adjustment I had to make -- I needed to make the .jpg files an hour later, not an hour earlier, but no problem, I just changed the -1 to +1.

Am I naive to believe that it would be easy for me to modify this function to change the Media Created time on my .mp4 files? Seems like I could just change the file extension(s) to be included in the "$Files = Get-ChildItem..." line, and then change the references to "DateTaken" to whatever the correct name is for the Media Created field. "MediaCreated"?

Thank you. Thank you. Thank you.
 


Back
Top