Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Перевести string в DateTime / 25 сообщений из 33, страница 1 из 2
01.03.2019, 12:28
    #39780927
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Подскажите пожалуйста, какой самый простой способ перевести string в TDateTime с нужным мне форматом?
Я хочу сделать так, что компьютер разбирался с форматом даты, а не я.

Только без возьни с TFormatSetting - это явно бред.
Что-то типа такого.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
var 
 ADate:TDateTime;
begin
 if not ConvertToDate(s,ADate, 'YYYY-MM-DD') then
 if not ConvertToDate(s,ADate, 'YYYY.MM.DD') then
 if not ConvertToDate(s,ADate, 'MM-DD-YYYY') then
и т.д.
end;
...
Рейтинг: 0 / 0
01.03.2019, 12:30
    #39780934
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Valery_B,

ну, всё правильно, и т.д. Т.е. еще несколько десятков вариантов. И молиться при этом, чтобы
01.02.2019 интерпретировалась как 'MM-DD-YYYY', а не как 'DD-MM-YYYY' или наоборот.
...
Рейтинг: 0 / 0
01.03.2019, 12:52
    #39780948
Barlone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Как-то так:
- а 01.02.2019 это второе января ли первое февраля?
- а я откуда знаю, компьютер умнее, он должен сам разобраться...
...
Рейтинг: 0 / 0
01.03.2019, 12:53
    #39780951
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Barlone- а 01.02.2019 это второе января ли первое февраля?
Да там и повеселее могут быть ситуации...

Например, 12.12.12
...
Рейтинг: 0 / 0
01.03.2019, 12:53
    #39780953
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
wadmanBarlone- а 01.02.2019 это второе января ли первое февраля?
Да там и повеселее могут быть ситуации...

Например, 12.12.12
Хотя...
в этом случае как раз супер-умный алгоритм не сможет ошибиться.
...
Рейтинг: 0 / 0
01.03.2019, 13:09
    #39780965
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Код: pascal
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.
function TForm7.StrToDateFrmt(const iFormat, iDateStr: string): TDateTime;
var
  AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word;
  aPos: Integer;

  procedure InitVars;
  begin
    AYear := 1;
    AMonth := 1;
    ADay := 1;
    AHour := 0;
    AMinute := 0;
    ASecond := 0;
    AMilliSecond := 0;
  end;

  function GetPart(const iPart: Char): Word;
  var
    aYCnt: Integer;
  begin
    Result := 0;
    aYCnt := 0;

    while (aPos <= High(iFormat)) and (iFormat.Chars[aPos + aYCnt] = iPart) do
      inc(aYCnt);

    Result := StrToInt(iDateStr.Substring(aPos, aYCnt));

    aPos := aPos + aYCnt;
  end;

begin
  InitVars;
  aPos := 0;

  while aPos <= High(iFormat) do
  begin
    case iFormat.Chars[aPos] of
      'Y':
        AYear := GetPart('Y');
      'M':
        AMonth := GetPart('M');
      'D':
        ADay := GetPart('D');
      'H':
        AHour := GetPart('H');
      'N':
        AMinute := GetPart('N');
      'S':
        ASecond := GetPart('S');
      'Z':
        AMilliSecond := GetPart('Z');
    else
      inc(aPos);
    end;
  end;

  Result := EncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, ASecond,
    AMilliSecond);
end;
...
Рейтинг: 0 / 0
01.03.2019, 13:12
    #39780967
Dimonka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Год отличить от не года - это не сложно, а с остальным сложнее.

Я как-то пробовал сделать алгоритм более менее универсальным и он даже иногда правильно выуживает даты, но временами не работает. Любые идеи по улучшению горячо приветствуются:

Те, кто не любит корявый код - не смотрите :-)
Код: pascal
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.
// функцию RegExp сам напишешь 
function RegExp(const Pattern, SMatch: string): string;

function ExtractDate(const Text: string): TDateTime;
var
  Pattern: string;
  s, d, m, y: string;
  YY, MM, DD: word;
  k: integer;
const
  MonthNames: string = 'jan feb mar apr may jun jul aug sep oct nov dec';
begin
  result := 0;
  Pattern := '(\d{4}\s[A-Za-z]{3,8}\s\d{1,2}|\d{1,2}\s[A-Za-z]{3,8}\s\d{4}|\d{4}[-\.\/]\d{1,2}[-\.\/]\d{1,2}|\d{1,2}[-\.\/]\d{1,2}[-\.\/]\d{4})';
  s := RegExp(Pattern, Text);
  if s <> '' then
  begin
    // extract year
    y := RegExp('(\d{4})', s);
    if y <> '' then
      YY := StrToInt(y)
    else
      exit;

    Pattern := '([a-zA-Z]+)';
    m := RegExp(Pattern, s);
    if m <> '' then
    begin
      // month as a word
      MM := pos(lowercase(copy(m, 1, 3)), MonthNames);
      if MM = 0 then
        exit;
      MM := (MM - 1) div 4 + 1;
      s := RegExp('(?<!\d)(\d{1,2})(?!\d)', s);
      if s = '' then
        exit;
      DD := StrToInt(s);
    end
    else
    begin
      // only numbers

      // get date and month
      s := RegExp('(?<!\d)(\d{1,2})(?!\d)', s);
      if s = '' then
        exit;
      k := pos(#13#10, s);
      if k = 0 then
        exit;

      D := copy(s, 1, k - 1);
      M := copy(s, k + 2, 255);

      dd := StrToInt(D);
      mm := StrToInt(M);
      // check if the date is in a sort of range
      if (not (dd in [1..12])) and (not(mm in [1..12]))   then
        exit;

      // try to guess by number what is what
      if dd > 12 then
      begin
        // this is a date
      end
      else
      if mm > 12 then
      begin
        // this is not a month

        // exchange day and month
        k := DD;
        DD := MM;
        MM := k;

      end
      else
      begin
        // check position of a year (first or last)
        if pos(y, s) > 4 then
        begin
          // year is in the end

          if Length(D) = 1 then
          begin
            // probably this is an american way of coding date
            // exchange day and month
            k := DD;
            DD := MM;
            MM := k;
          end;

        end
        else
        begin
          // year is in the beginning

          // exchange day and month
          k := DD;
          DD := MM;
          MM := k;
        end;
      end;
    end;
    if (DD in [1..31]) and (MM in [1..12]) then
    begin
      if not TryEncodeDate(YY, MM, DD, result) then
        result := 0;
    end;
  end;
end;

...
Рейтинг: 0 / 0
01.03.2019, 13:29
    #39780975
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
wadmanwadmanпропущено...

Да там и повеселее могут быть ситуации...

Например, 12.12.12
Хотя...
в этом случае как раз супер-умный алгоритм не сможет ошибиться.
Да ну. год 0012, 1912, 2012...
...
Рейтинг: 0 / 0
01.03.2019, 13:34
    #39780982
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
BarloneКак-то так:
- а 01.02.2019 это второе января ли первое февраля?
- а я откуда знаю, компьютер умнее, он должен сам разобраться...
"Программа сама должна знать, что нужно, а что не нужно".

В общем-то, такая программа давно написана.
http://button.dekel.ru/
...
Рейтинг: 0 / 0
01.03.2019, 13:48
    #39780995
L_argo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Я делал ф-цию, на вход кот. передавал разбираемую строку и вероятный формат (ГМД, ДМГ, МДГ)
Любое нечисло это разделитель.
Бил строку на части, проверял на ошибки (мес 1..12, день 1..31), год подгонял до тысяч, если он короткий.
Потом из частей получал дату-время.
...
Рейтинг: 0 / 0
01.03.2019, 13:57
    #39781006
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Barlone - а 01.02.2019 это второе января ли первое февраля?

А ты сам-то можешь однозначно ответить на этот вопрос ? Подозреваю - что нет.
Точно так же, поступит и компьютер.
Первое с чего должна начинаться конвертация - это с локального формата времени.
Если она не получилась, пусть дальше работает.

Мне ну совсем не хочется разбираться, какой разделитель стоит "-", "." или даже ",".
Также, если первым или последним идёт число "2019" (т.е. "четырёхзначное")
Думаю, что 8 ядерный CoreI7 в состоянии сам разобраться ?
...
Рейтинг: 0 / 0
01.03.2019, 14:00
    #39781009
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Кстати, строки могут ещё иметь и такой формат +-:
автор2019-03-01T00:00:00.000000
2019-03-01T10:59:16.657Z
2019-03-01T10:59:16.657Z +03
...
Рейтинг: 0 / 0
01.03.2019, 14:01
    #39781010
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Valery_B
Код: pascal
1.
ConvertToDate(s,ADate, 'YYYY-MM-DD')



функция sscanf ?
...
Рейтинг: 0 / 0
01.03.2019, 14:13
    #39781016
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Valery_BМне ну совсем не хочется разбираться, какой разделитель стоит "-", "." или даже ",".

Наверное, надо делать так.
Осталось только с форматом определится...
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function ConvertToDate(const DateStr:string):TDateTime;
var
 s:string;
begin
 s:=StringReplace(DateStr,',','.');
 s:=StringReplace(s,'-','.');
 s:=StringReplace(s,' ','.');
 s:=StringReplace(s,'_','.');
//т.е. все возможные разделители сначала привести к одному.
end;
...
Рейтинг: 0 / 0
01.03.2019, 14:13
    #39781017
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Ariochфункция sscanf ?

автор[Error] Unit1.pas(27): Undeclared identifier: 'sscanf'
...
Рейтинг: 0 / 0
01.03.2019, 14:21
    #39781025
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Valery_BДумаю, что 8 ядерный CoreI7 в состоянии сам разобраться ?
Если-б он мог, то была-бы тема?
...
Рейтинг: 0 / 0
01.03.2019, 14:40
    #39781038
vavan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Dimonka, "если у вас есть проблема и вы собираетесь решить ее регулярными выражениями – теперь у вас две проблемы" (С)
...
Рейтинг: 0 / 0
01.03.2019, 15:00
    #39781059
Dimonka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
vavanDimonka, "если у вас есть проблема и вы собираетесь решить ее регулярными выражениями – теперь у вас две проблемы" (С) Третья проблема была в том, что это всё делалось в PascalScript :-) Так что проблем было куда больше.
...
Рейтинг: 0 / 0
01.03.2019, 15:03
    #39781063
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Valery_B, ты бы озвучил откуда ты получаешь строки. Если их вводит пользователь, то не надо вообще пробовать что-то иное окромя локального формата даты.
...
Рейтинг: 0 / 0
01.03.2019, 15:12
    #39781067
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
GunSmoker,

В контролы Edit/DateEdit должен безпроблемно вставляться текст(CTRL+V).
От куда берётся(CTRL+C) - неизвестно. Пусть из Excel
...
Рейтинг: 0 / 0
01.03.2019, 15:23
    #39781072
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
На самом деле, в реальности всего получается только 2 формата даты:
1. Общепринятый - DD MM YYYY
2. Компьютерный - YYYY MM DD

01.02.2019 - это 01 Февраля 2019г.

Видимо, надо будет создать 2 FormatSettings с разными форматами дат.
Разделители, привести к чему-то единому через StringReplace.
Всё остальное скорее всего будет не дата.
...
Рейтинг: 0 / 0
01.03.2019, 15:42
    #39781079
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Valery_B,

А вот Америка пишет - MM/DD/YYYY
...
Рейтинг: 0 / 0
01.03.2019, 15:48
    #39781082
MirnyiAtom
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
Я бы делал так:
регулярным выражением посчитал бы количество цифр в начале строки, что бы определиться с форматом

регуляркой поменял бы все не цифры на точку

преобразование

и отлов ошибок, конечно.
...
Рейтинг: 0 / 0
01.03.2019, 15:57
    #39781087
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
MirnyiAtomрегуляркой поменял бы все не цифры на точкуБыло
2019-03-01T12:08:33.654-02:00
стало
2019.03.01.12.08.33.654.02.00

Удачного парсинга
...
Рейтинг: 0 / 0
01.03.2019, 16:34
    #39781117
Valery_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перевести string в DateTime
zinpubValery_B,

А вот Америка пишет - MM/DD/YYYY
Значит надо сделать так, что бы в америке писали YYYY MM DD
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Перевести string в DateTime / 25 сообщений из 33, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]