Блог Александра Божко
Архивы
Рубрики
Поделись с другими!
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Казалось бы количество версий Delphi перевалило за два десятка, и уж белых пятен, по крайней мере  относительно функций даты и времени, быть не должно. Действительно, появившийся, если не ошибаюсь, в Delphi 7, модуль DateUtils, казалось бы снимает все вопросы. Однако, не тут то было!

В доставшемся мне от предшественников проекте я тщательно вычистил функции подобные StartOfTheWeek или StartOfTheDay. Первая версия проекта была написана, похоже, на Delphi 5, в которой DateUtils просто еще не было. Потом этот модуль появился, а я, унаследовав проект, решил, что нет смысла таскать “лишний” код, а проще подключить DateUtils. И вот недавно я получил получил забавный баг. Приложение определяет всегда первый день недели – понедельник. Хотя, у большинства пользователей первым днем является воскресенье.

Первым делом проверил StartOfTheWeek, и с удивлением обнаружил, что и в самом деле, функция всегда возвращает начало понедельника, в качестве результата. А соответствующий справки содержит следующую ремарку:

Note:StartOfTheWeek defines the week of AValue according to the ISO 8601 standard. That is, the week starts on Monday and ends on Sunday.

Лично мне не совсем понятно, почему данная функция реализована именно так, тем не менее, факт остается фактом. Но, как в свое время говаривала Лия Ахиджакова: “Надо что-то с этим делать, бороться как-то!”

Смотрим код функции:

function StartOfTheWeek(const AValue: TDateTime): TDateTime;
begin
  Result := Trunc(AValue) - (DayOfTheWeek(AValue) - 1);
end;

Как видим, в коде используется функция DayOfTheWeek, которая так же считает, что первым днем недели является понедельник. Код функции такой:

 

function DayOfTheWeek(const AValue: TDateTime): Word;
begin
  Result := (DateTimeToTimeStamp(AValue).Date - 1) mod 7 + 1;
end;
 

Проблема заключается в том, что бы определить какой же день недели является первым. Для этого используем API функцию GetLocaleInfo. Я на скорую руку реализовал такие функции:

function GetLocaleInformation(Flag: Integer): string;
var
  Buffer    : PChar;
  Size      : integer;
  LocaleName: String;
begin
  Size := GetLocaleInfo (LOCALE_SYSTEM_DEFAULT, Flag, nil, 0);
  GetMem(Buffer, Size);
  try
    GetLocaleInfo (LOCALE_SYSTEM_DEFAULT, Flag, Buffer, Size);
    Result := string(Buffer);
  finally
    FreeMem(Buffer);
  end;
 
end;
 
function StartOfWeek(const AValue: TDateTime): TDateTime;
var
fDay, dow: integer;
begin
 
fDay:=
  StrToIntDef(GetLocaleInformation(LOCALE_IFIRSTDAYOFWEEK), 0);
  Result := Trunc(AValue) - ((DateTimeToTimeStamp(AValue).Date - fDay-1) mod 7);
 
end;

В принципе, ничего сложного. Конечно же нужно не забыть и о функции EndOfTheWeek.

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

 


Поделись с другими!
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

2 комментария: О StartOfTheWeek…

  • Все-таки это не баг, а фича, т.к. к StartOfTheWeek есть “парная” функция StartOfWeek, которая всегда (sic!) возвращает воскресенье.
    Согласен, недоработка в смысле отсутствия автоматического определения по текущей локали. Хотя, если подумать, а если надо что-то получить вне зависимости от локали???

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Продукты DevArt
Купить онлайн:



Читай русскоязычные Delphi блоги
Каталог блогов Blogdir.ru
Яндекс.Метрика