Этот вопрос можно преобразовать в “как преобразовать 20160911195120 в 11.09.2016 19:51:20 и перевести в LocalTime?”
Я также поднял этот вопрос на 2 форумах
Также мне показалась интересной ссылка на TTimeZone – класса, который появился, начиная с Delphi XE и избавил нас, в какой-то степени от зависимости от WinAPI
В сущности, получить даты создания, изменения и последнего доступа в Indy несложно, сделать это можно вот так…
1 2 3 4 5 6 7 8 9 10 11 |
... IdFTP.List; // List info from Server Memo1.Lines.Clear; for i := 0 to IdFTP.ListResult.Count-1 do begin Memo1.Lines.Add(IdFTP.ListResult[i]); end; ... |
Мы получим примерно вот такой результат
Как вытащить его оттуда? Да с помощью регулярок. Я чуть позже, в данном посте покажу как я это сделал. Мы получим число в формате 20160911195120. Но если распарсить его, то оно не локализовано, оно в GMT 0;
Как преобразовать 20160911195120 в 11.09.2016 19:51:20 и перевести в LocalTime?
Вопрос в другом – что далее с этим делать? Хотелось бы получить стандартную для Delphi дату и стандартное время в формате 11.06.2016 19:51:20.
Если присмотреться – это число состоит как раз из YYYY:MM:DD:HH:MM:SS – распарсить его несложно, например, при помощи вот такой функции
1 2 3 4 5 6 7 8 |
IndyString:='20160912210450'; // <<Example datetime := EncodeDateTime(StrToInt(Copy(IndyString, 1, 4)), StrToInt(Copy(IndyString, 5, 2)), StrToInt(Copy(IndyString, 7, 2)), StrToInt(Copy(IndyString, 9, 2)), StrToInt(Copy(IndyString, 11, 2)), StrToInt(Copy(IndyString, 13, 2)), 0); |
Но если сравнить полученные результат с часами на Windows, то получится, в большинстве случаев – разница на GMT. Скажем у меня была разница в 5 часов. Время, записанное для файла было 19:51:20, а время на часах Windows 19:51:20 + 5 часов.
Indy, насколько я понимаю, выдаёт это число в GMT 0. Но что с ним делать дальше, даже после парсинга? Я провозился часа 3 над вопросом и у меня созрело вот такое решение.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
procedure TVisualFrame_PSFTPClient.bTestClick(Sender: TObject); var FFileTimeLocalized:TFileTime; FFileTime:TFileTime; FLocalFileTime:TFileTime; SystemTimeLocalized:TSystemtime; SystemTime:TSystemtime; datetime: TDateTime; IndyString:String; begin IndyString:='20160912210450'; // <<Example datetime := EncodeDateTime(StrToInt(Copy(IndyString, 1, 4)), StrToInt(Copy(IndyString, 5, 2)), StrToInt(Copy(IndyString, 7, 2)), StrToInt(Copy(IndyString, 9, 2)), StrToInt(Copy(IndyString, 11, 2)), StrToInt(Copy(IndyString, 13, 2)), 0); // Localizing DateTime... DateTimeToSystemTime(datetime,SystemTime); SystemTimeToFileTime(SystemTime,FFileTime); FileTimeToLocalFileTime(FFileTime,FFileTimeLocalized); FileTimeToSystemTime(FFileTimeLocalized,SystemTimeLocalized); ShowMessage( 'GMT Localized '+ DateTimeToStr( SystemTimeToDateTime( SystemTimeLocalized)) ); ShowMessage( 'GMT 0 (Not Localized) '+ DateTimeToStr(datetime) ); end; |
Теперь результат выдается корректно. Я написал это в виде функции
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
function TVisualFrame_PSFTPClient.IndyStringToLocalizeDateTimeString(IndyString:string):string; var FFileTimeLocalized:TFileTime; FFileTime:TFileTime; FLocalFileTime:TFileTime; SystemTimeLocalized:TSystemtime; SystemTime:TSystemtime; datetime: TDateTime; begin //if IndyString='' then begin // Result:=''; Exit; //end; //IndyString:='20160912210450'; // <<Example datetime := EncodeDateTime(StrToInt(Copy(IndyString, 1, 4)), StrToInt(Copy(IndyString, 5, 2)), StrToInt(Copy(IndyString, 7, 2)), StrToInt(Copy(IndyString, 9, 2)), StrToInt(Copy(IndyString, 11, 2)), StrToInt(Copy(IndyString, 13, 2)), 0); DateTimeToSystemTime(datetime,SystemTime); SystemTimeToFileTime(SystemTime,FFileTime); FileTimeToLocalFileTime(FFileTime,FFileTimeLocalized); FileTimeToSystemTime(FFileTimeLocalized,SystemTimeLocalized); //Localized DateTime Result:= DateTimeToStr(SystemTimeToDateTime( SystemTimeLocalized)); { ShowMessage( 'GMT Localized '+ DateTimeToStr( SystemTimeToDateTime( SystemTimeLocalized)) ); ShowMessage( 'GMT 0 (Not Localized) '+ DateTimeToStr(datetime) ); } end; |
Как вытащить 20160911195120 из массива данных при помощи регулярок?
Итак, есть у нас набор данных, выглядит он вот так…
Как вытащить дату и время создания и локализовать его?
Думаю, варианты тут разные возможны. Но вариант с регулярками мне показался оч. интересным и простым по реализации. Добавим TEdit на форму, для экспериментов с регулярками. Сразу посмотрим на результат
Показываю здесь кусок кода, который отвечает за вытаскивание, ниже покажу весь кусок кода на тестовой кнопке… Идея здесь в чем?
Сначала вытаскиваем все create=20160912214206 в отдельную коллекцию совпадений, потом вытаскиваем уже только 20160912214206 в другую коллекцию совпадений. Ну и собственно, загружаем это все в Memo, для иллюстрации.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
... Uses RegularExpressions ... var RegEx: TRegEx; M: TMatchCollection; // j,k: integer; M2:TMatchCollection; //Regular Expressions //Сначала выделим все фразы create=20160912214206 Edit1.Text:='create=[\d]*[\d]\b'; RegEx:=TRegEx.Create(Edit1.Text); // <<Что ищем try if IdFTP.Connected then begin //ОСНОВНАЯ РАБОТА ЗДЕСЬ with idFTP do begin ChangeDir(CurrentDir); List; Memo1.Lines.Clear; for i := 0 to IdFTP.ListResult.Count-1 do begin //Memo1.Lines.Add(IdFTP.ListResult[i]); M:=RegEx.Matches(IdFTP.ListResult[i],Edit1.Text); for j := 0 to M.Count-1 do begin //Memo1.Lines.Add(M.Item[j].Value); M2:=RegEx.Matches(M.Item[j].Value,'[\d]*[\d]\b'); for k := 0 to M2.Count-1 do begin Memo1.Lines.Add(M2.Item[j].Value); end; end; end; for i := 0 to Memo1.Lines.Count-1 do begin // Memo2.Lines.Add(' CreationDateTime '+ IndyStringToLocalizeDateTimeString(Memo1.Lines[i]) ); end; // FileDateToDateTime end; end; finally idFTP.Disconnect; FreeAndNil(RegEx); end; ... |
Полный код тестовой кнопки выглядит вот так…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
procedure TVisualFrame_PSFTPClient.bTest2Click(Sender: TObject); var I: integer; RegEx: TRegEx; M: TMatchCollection; j,k: integer; M2:TMatchCollection; begin with idFTP do begin Host:=FTPConnectionParams.Host;// 'localhost'; //FTP-сервер Port:=FTPConnectionParams.Port;// 22; //порт ФТП сервера Username:=FTPConnectionParams.Username;// 'Логин'; Password:=FTPConnectionParams.Password;// 'Пароль'; end; try idFTP.Connect; try //Regular Expressions Edit1.Text:='create=[\d]*[\d]\b'; RegEx:=TRegEx.Create(Edit1.Text); //Что ищем ^c[\w]+;\b try if IdFTP.Connected then begin //ОСНОВНАЯ РАБОТА ЗДЕСЬ with idFTP do begin ChangeDir(CurrentDir); List; Memo1.Lines.Clear; for i := 0 to IdFTP.ListResult.Count-1 do begin //Memo1.Lines.Add(IdFTP.ListResult[i]); M:=RegEx.Matches(IdFTP.ListResult[i],Edit1.Text); for j := 0 to M.Count-1 do begin //Memo1.Lines.Add(M.Item[j].Value); M2:=RegEx.Matches(M.Item[j].Value,'[\d]*[\d]\b'); for k := 0 to M2.Count-1 do begin Memo1.Lines.Add(M2.Item[j].Value); end; end; end; for i := 0 to Memo1.Lines.Count-1 do begin // Memo2.Lines.Add(' CreationDateTime '+ IndyStringToLocalizeDateTimeString(Memo1.Lines[i]) ); end; // FileDateToDateTime end; end; finally idFTP.Disconnect; FreeAndNil(RegEx); end; except //Other exceptions on E: EIdException do begin raise Exception.Create(E.ClassName+' An network error occurred during communication: ' +#13#10+#13#10+E.Message); end; on E: Exception do begin raise Exception.Create(E.ClassName+' An unknown error occurred during communication: ' +#13#10+#13#10+E.Message); end; end; except // Catching Connection Exceptions on E: EIdException do begin raise Exception.Create(E.ClassName+' An network error occurred while trying to connect: ' +#13#10+#13#10+E.Message); end; on E: Exception do begin raise Exception.Create(E.ClassName+'An unknown error occurred while trying to connect: ' +#13#10+#13#10+E.Message); end; end; end; |