Что нового

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

Пётр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,671
Репутация
2,481
Что не так в скрипте?
Всё :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,671
Репутация
2,481
Оказывается, это специфика системы, всё дело в настройках коррекции времени и файловой системе.
Это нужно учитывать при получении времени.
Есть также тикет на оф. форуме, там даже предлагают вариант решения, у меня с этим вариантом показывает на 3 часа позже (видимо из за +3 в моём часовом поясе).
Я советую оставить как есть, т.к это и есть правильное время которое должно отображаться системой.
 

CreatoR

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

Код:
#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,671
Репутация
2,481
Мой вариант скрипта хорош, вероятно, лишь тем, что он совершенно прозрачен/прост
Ну я бы не сказал что он прост. Кстати есть ещё функция 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,671
Репутация
2,481
Какую сложность видите Вы?
Ну всё познаётся в сравнении...
По мне так намного проще соединить несколько переменных (ячейки массива) чем выдирать данные из текстового значения используя строковые функции.
Да и получение списка файлов проще делать готовой для этого функцией.
Другое дело - стоИт ли вопрос скорости, если да, то вариант с FileFindFirstFile / FileFindNextFile вроде будет быстрее.
 
Верх