Что нового

Экстракция и препарация даты модификации файла - неправильное указание часа

Пётр325958

Новичок
Сообщения
14
Репутация
0
Доброго времени, уважаемый форум!

Задача:
Взять время модификации из свойств файла и перевести его в формат гггг.мм.дд-чч.мм.сс. Файлы с датами модификации:
1. 10.09.2018 10:46:45
2. 02.01.2009 1:55:54
3. 07.03.2009 17:48:55
4. 25.07.2005 9:59:48

Проблема:
Приведённый ниже скрипт для 2го и 3го файлов указывает неправильный час: в обоих случаях +1 час.
Код:
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>

   Local $hSearch = FileFindFirstFile("C:\...\*.ico")
    Local $sFileName = ""
    While 1
        Local $Year = "", $Month = "", $Day = "", $Hour = "", $Minute = "", $Second = ""
        $sFileName = FileFindNextFile($hSearch)
        If @error Then ExitLoop
      
        ; MsgBox($MB_SYSTEMMODAL, "", "File: " & $sFileName)
      
        $FileModifTime = FileGetTime("C:\...\" & $sFileName,0,1)
        ; MsgBox($MB_SYSTEMMODAL, "", "$FileModifTime: " & $FileModifTime)
        ; $FileModifTime = StringTrimRight($FileModifTime,6)
        MsgBox($MB_SYSTEMMODAL, "", "$FileModifTime: " & $FileModifTime)
        $Year = StringTrimRight($FileModifTime,10)
        $Month = StringTrimRight($FileModifTime,8)
        $Month = StringTrimLeft($Month,4)
        $Day = StringTrimRight($FileModifTime,6)
        $Day = StringTrimLeft($Day,6)
        $Hour = StringTrimRight($FileModifTime,4)
        MsgBox($MB_SYSTEMMODAL, "", "$Hour: " & $Hour)
        $Hour = StringTrimLeft($Hour,8)
        MsgBox($MB_SYSTEMMODAL, "", "$Hour: " & $Hour)
        $Minute = StringTrimRight($FileModifTime,2)
        $Minute = StringTrimLeft($Minute,10)
        $Second = StringTrimLeft($FileModifTime,12)     
        $ModifDatePrepared = $Year & "." & $Month & "." & $Day & "-" & $Hour & "." & $Minute & "." & $Second
        MsgBox($MB_SYSTEMMODAL, "", "$ModifDatePrepared: " & $ModifDatePrepared)
    WEnd
    FileClose($hSearch)
Вопрос:
Что не так в скрипте?
 
Последнее редактирование:

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 402
Что не так в скрипте?
Всё :stop: .

Код:
#include <File.au3>
#include <MsgBoxConstants.au3>

$sPath = 'C:\'
$sFilter = '*.ico'

$aFiles = _FileListToArray($sPath, $sFilter, $FLTA_FILES, False)
If @error Then Exit

For $i = 1 To $aFiles[0]
    $aTime = FileGetTime($sPath & '\' & $aFiles[$i], $FT_MODIFIED, $FT_ARRAY)
    If @error Then ContinueLoop
    
    $sModDate = $aTime[0] & $aTime[1] & $aTime[2] & $aTime[3] & $aTime[4] & $aTime[5]
    $sFrmtddModDate = $aTime[0] & '.' & $aTime[1] & '.' & $aTime[2] & '-' & $aTime[3] & '.' & $aTime[4] & '.' & $aTime[5]
    
    MsgBox($MB_SYSTEMMODAL, $aFiles[$i], 'Mod. date: ' & $sModDate)
    MsgBox($MB_SYSTEMMODAL, $aFiles[$i], 'Formated mod. date: ' & $sFrmtddModDate)
Next
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 402
Оказывается, это специфика системы, всё дело в настройках коррекции времени и файловой системе.
Это нужно учитывать при получении времени.
Есть также тикет на оф. форуме, там даже предлагают вариант решения, у меня с этим вариантом показывает на 3 часа позже (видимо из за +3 в моём часовом поясе).
Я советую оставить как есть, т.к это и есть правильное время которое должно отображаться системой.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 402
Попробуйте так (нашёл на оф. форуме):

Код:
#include <Date.au3>
#include <File.au3>
#include <WinAPIFiles.au3>
#include <WinAPI.au3>
#include <MsgBoxConstants.au3>

$sPath = 'C:\'
$sFilter = '*.ico'

$aFiles = _FileListToArray($sPath, $sFilter, $FLTA_FILES, False)
If @error Then Exit

For $i = 1 To $aFiles[0]
    $aTime = FileGetTimeExt($sPath & '\' & $aFiles[$i], $FT_MODIFIED, $FT_ARRAY)
    If @error Then ContinueLoop
    
    $sModDate = $aTime[0] & $aTime[1] & $aTime[2] & $aTime[3] & $aTime[4] & $aTime[5]
    $sFrmtddModDate = $aTime[0] & '.' & $aTime[1] & '.' & $aTime[2] & '-' & $aTime[3] & '.' & $aTime[4] & '.' & $aTime[5]
    
    MsgBox($MB_SYSTEMMODAL, $aFiles[$i], 'Mod. date: ' & $sModDate)
    MsgBox($MB_SYSTEMMODAL, $aFiles[$i], 'Formated mod. date: ' & $sFrmtddModDate)
Next

Func FileGetTimeExt($filename, $option = 0, $format = 0)
    ; v1.0
    ; Extended FileGetTime function to properly deal with DST (Daylight Saving Time (summertime/wintertime)) on Windows 7+
    ; Usage is identical to the FileGetTime.
    
    If $option = Default Then $option = 0
    If $format = Default Then $format = 0
    Local $sDrive = "", $sDir = "", $sFileName = "", $sExtension = "", $ssDir = "", $sDummy1 = "", $sDummy2 = ""
    _PathSplit($filename, $sDrive, $sDir, $sFileName, $sExtension)
    ; extend path to full path if filename has no path or a path relative to ScriptDir
    If $sDrive = "" Then
        _PathSplit(@ScriptFullPath, $sDrive, $ssDir, $sDummy1, $sDummy2)
        $sDir = $ssDir & $sDir
        $filename = _PathMake($sDrive, $sDir, $sFileName, $sExtension)
    EndIf
    Local $aTime, $tDate, $tOut[6], $hFile, $tSystem, $tLocal, $tFile
    FileGetTime($filename, $option, $format) ; test if no error occurs
    If @error Then Return SetError(@error, 0, "")
    ; use _WinAPI_CreateFileEx instead of _WinAPI_CreateFile to include directory access without an 'Access is denied' error
    $hFile = _WinAPI_CreateFileEx($filename, $OPEN_EXISTING, $GENERIC_READ, $FILE_SHARE_READ, $FILE_FLAG_BACKUP_SEMANTICS)
    Switch $option ; convert FileGetTime option 0 to _Date_Time_GetFileTime option 2, 1 to 0 and 2 to 1
        Case 0
            $option = 2 ; Last modified (default)
        Case 1
            $option = 0 ; Created
        Case 2
            $option = 1 ; Last accessed
    EndSwitch
    $aTime = _Date_Time_GetFileTime($hFile)
    _WinAPI_CloseHandle($hFile)
    $aTime = $aTime[$option]
    $tSystem = _Date_Time_FileTimeToSystemTime($aTime)
    $tLocal = _Date_Time_SystemTimeToTzSpecificLocalTime($tSystem)
    $tFile = _Date_Time_SystemTimeToFileTime($tLocal)
    $tDate = _Date_Time_FileTimeToArray($tFile)
    $tOut[0] = StringFormat("%04i", $tDate[2]) ; Year
    $tOut[1] = StringFormat("%02i", $tDate[0]) ; Month
    $tOut[2] = StringFormat("%02i", $tDate[1]) ; Day
    $tOut[3] = StringFormat("%02i", $tDate[3]) ; Hour
    $tOut[4] = StringFormat("%02i", $tDate[4]) ; Minutes
    $tOut[5] = StringFormat("%02i", $tDate[5]) ; Seconds
    If $format = 0 Then Return SetError(0, 0, $tOut)
    Return SetError(0, 0, $tOut[0] & $tOut[1] & $tOut[2] & $tOut[3] & $tOut[4] & $tOut[5])
EndFunc
 
Автор
П

Пётр325958

Новичок
Сообщения
14
Репутация
0
Благодарю Вас, CreatoR, за подробный разбор моего вопроса!
С интересом прочёл разборку по указанному Вами адресу :smile: . ...What a pain!...
Я последую Вашему совету и оставлю как есть.
Мой вариант скрипта хорош, вероятно, лишь тем, что он совершенно прозрачен/прост.
Очевидно, дело в часовых поясах. У меня в Win10 выставлено UTC +1.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 402
Мой вариант скрипта хорош, вероятно, лишь тем, что он совершенно прозрачен/прост
Ну я бы не сказал что он прост. Кстати есть ещё функция StringMid :blush: :

Код:
$Year = StringLeft($FileModifTime, 4)
$Month = StringMid($FileModifTime, 5, 2)
$Day = StringMid($FileModifTime, 7, 2)
$Hour = StringMid($FileModifTime, 9, 2)
$Minute = StringMid($FileModifTime, 11, 2)
$Second = StringRight($FileModifTime, 2)
 
Автор
П

Пётр325958

Новичок
Сообщения
14
Репутация
0
Ну я бы не сказал что он прост.
Вижу в нём сложность в структуре FileFindFirstFile / FileFindNextFile , на которой построен поиск и обращение к отдельным результатам поиска (ну кроме While...).
Это оказалось проще, так как мне не пришлось разбираться с выводом данных из массива. С функциями FileFindFirstFile / FileFindNextFile к моменту написания скрипта
до степени получения приемлемых результатов я уже разобрался :mocking:.
Сложность в том, что эти функции создают handle, а не "прямой" текст/результат поиска, который можно извлечь из $Search.
Может быть я упустил что-нибудь? Какую сложность видите Вы? (Ну если есть время/желание прокомментировать, конечно.)
Кстати есть ещё функция StringMid
Да, спасибо, что напомнили! Её действительно разумно тут использовать. Упустил её из виду.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 402
Какую сложность видите Вы?
Ну всё познаётся в сравнении...
По мне так намного проще соединить несколько переменных (ячейки массива) чем выдирать данные из текстового значения используя строковые функции.
Да и получение списка файлов проще делать готовой для этого функцией.
Другое дело - стоИт ли вопрос скорости, если да, то вариант с FileFindFirstFile / FileFindNextFile вроде будет быстрее.
 
Верх