Перейти к содержанию

Функция перевода строки с датой в стандарт дд.мм.гггг - Тестируем


Рекомендуемые сообщения

В общем написал такую штуку, которая должа съедать любой формат строки и выдавать дату в виде строки в формате дд.мм.гггг.

Например:

1. Ввод: 1-2-3

Вывод: 01.02.2003

2.Ввод: 1

Вывод: 01.07.2008

(То есть считает, что забит день текущего месяца)

3.Ввод: 133

Вывод: 13.03.2008

и т.д.

Надо потестировать, найти ошибки. Если кто хочет, может оптимизировать :)

p.s. Работает на Delphi.

function textToDate(Txt:TCaption):TCaption;
var day,month,year:TCaption;
i,iday,imonth,iyear:integer;
nd,nm,ny:word;
begin
iday:=0;
imonth:=0;
iyear:=0;
for i:=1 to length(txt) do
begin
if txt[i] in ['1','2','3','4','5','6','7','8','9','0'] then
begin
if iday<2 then
begin
day:=day+txt[i];
inc(iday);
end
else
if imonth<2 then
begin
month:=month+txt[i];
inc(imonth);
end
else
if iyear<4 then
begin
year:=year+txt[i];
iyear:=iyear+1;
end;
end
else
begin
if iday=1 then
begin
iday:=2;
day:='0'+day;
end;
if imonth=1 then
begin
imonth:=2;
month:='0'+month;
end;
if iyear=1 then
begin
iyear:=4;
year:='200'+year;
end;
if iyear=2 then
begin
iyear:=4;
if year[1]>'5' then
year:='19'+year
else
year:='20'+year;
end;
if iyear=3 then
begin
iyear:=4;
year:='1'+year;
end;
end;
end;
Decodedate(now,ny,nm,nd);
case iyear of
0: begin
year:=inttostr(ny);
iyear:=4;
end;
1: year:='200'+year;
2: if year[1]>'5' then
year:='19'+year
else
year:='20'+year;
3: year:='1'+year;
end;
if iday=0 then day:=inttostr(nd);
if imonth=0 then month:=inttostr(nm);

iday:=strtoint(day);
imonth:=strtoint(month);

if length(day)<2 then
day:='0'+day;
if length(month)<2 then
month:='0'+month;

if iday=0 then
day:='01';
if imonth=0 then
month:='01';

if (imonth in [4,6,9,11]) and (iday>30) then
day:='30';
iyear:=strtoint(year[3]+year[4]);
if (imonth=2) and (iday>28) then
if (iday>29) and ((iyear mod 4)=0) and (iyear<>0) then
day:='29'
else
day:='28';
texttodate:=day+'.'+month+'.'+year;
end;

Добавлено спустя 1 минуту 24 секунды:

Если не понятен алгоритм, спрашивайте. Вечером опишу по-подробнее.

Ссылка на комментарий

если есть две цыфры подряд - он считает их как число, следующую пару - как месяц и т.д.

ВВод по маске автоматически не подставляют месяц и год - поэтому не подходят.

Ссылка на комментарий

для ускорения ввода документов, самое оно, а юзеры тыкнутся пару раз неправильно, но потом привыкнут,

просто рядом можно в Label выводить, что получается,

типа в Edit1Change вызывать эту функцию

Label1.Caption := textToDate(Edit1.Text);

и результат сразу будет видно

Ссылка на комментарий

bayarookie

я знаю. Это я еще и написал!

Так и работает. Просто я не могу ошибок найти в работе, вот и выложил, может вы ее сможете "сломать".

Фишка в том, что вводить можно ЛЮБОЙ текст, она его должна пережовывать и выдавать дату.

Может кто сможет код оптимизировать.

ТОка не на Change а на Exit :)

Еще алгоритм написан таким образом, чтобы легко можно было его перевести на С++ и другие языки.

Добавлено спустя 3 минуты 3 секунды:

Тут даже учтено исправление даты, если месяц 30 дней или 31, а также февраль в нормальный и весокосный год.

Добавлено спустя 3 минуты 42 секунды:

Ввводим:

34хер1не5

Получаем:

31.01.2005

Ссылка на комментарий

блин. Вообщето должен выдавать 31 июля.

Добавлено спустя 1 минуту 59 секунд:

хотя логичнее 5 февраля. ЩАс переделаю.

Добавлено спустя 34 минуты 19 секунд:

function textToDate(Txt:TCaption):TCaption;
var day,month,year:TCaption;
i,iday,imonth,iyear:integer;
nd,nm,ny:word;
begin
iday:=0;
imonth:=0;
iyear:=0;
for i:=1 to length(txt) do
begin
if txt[i] in ['1','2','3','4','5','6','7','8','9','0'] then
begin
if iday<2 then
begin
if (iday=2) and (strtoint(day)>=4) then
begin
day:='0'+day;
inc(imonth);
month:=txt[i];
end
else
day:=day+txt[i];
inc(iday);
end
else
if imonth<2 then
begin
month:=month+txt[i];

//.......................................

if imonth>12 then
begin
month:='12';
imonth:=12;
end;
if (imonth in [4,6,9,11]) and (iday>30) then
day:='30';
if (imonth in [1,3,5,7,8,10,12]) and (iday>31) then
day:='31';
iyear:=strtoint(year[3]+year[4]);
if (imonth=2) and (iday>28) then
if (iday>29) and ((iyear mod 4)=0) and (iyear<>0) then
day:='29'
else
day:='28';
texttodate:=day+'.'+month+'.'+year;
end;

Подправленные места.

Теперь логика такая - если первая цифра дня больше 4, то следующая цифра относится к месяцу (если они не разделены разделителем)

Добавлено спустя 1 минуту 19 секунд:

еще думаю с месяцами тоже проделать, если 523, то вводилось 05.02.2003 (щас 05.12.2008)

Ссылка на комментарий

так получше

а всё-таки лучше в OnChange делать, чем в OnExit, потому что, например, могут ввести что-то неправильно и сразу мышкой нажать кнопку "Сохранить"

Ссылка на комментарий

Эту функцию можно отнести к обработчикам текста после его ввода. Если обрабатывать текст одновременно с вводом, то там геморроя больше получается, т.к. приходится обрабатывать текст и последнюю нажатую клавишу (если BackSpace - то изменять ничего не надо - просто пользователь исправляет, а если цыферы, то смотреть, что вводит и исправлять, потом сравнивать месяц и день - если нужно исправлять день, а потом выяснять високосность года и опять исправлять день, если год НЕ високосный).

Ссылка на комментарий

нажатая клавиша - это в OnKeyPress и OnKeyDown и OnKeyUp,

а в OnChange - только когда меняются данные

procedure TForm1.Edit1Change(Sender: TObject);
begin
Label1.Caption := textToDate(Edit1.Text);
end;

вот так вот работает просто отлично

Ссылка на комментарий

Ухаха... Прикольный способ :thumbs:

Но наверно всётаки надо выводить туда-же, потомучто "тупой" пользователь не поймет, как это - пишу тут, а пишется там. Да и к томуже не для всех языков подойдет этот способ.

Ссылка на комментарий

Пожалуйста, войдите, чтобы комментировать

Вы сможете оставить комментарий после входа в



Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...