Выдалась под вечер свободная минутка и решил немного покодить. В целом проблем с вопросом "Что кодить?" не возник, т.к. открытых тем в блоге валом,но решил продолжить работы над Google API. Когда начинал работу над Google Celendar API, то совершенно упустил из виду простой, но вместе с тем полезный модуль. Молуль, содержащий вспомогательные величины, константы, ресурсные строки и т.д. для работы с API в целом. Чертовски неудобно и нехорошо каждый раз в кажом модуле вспоминать про то, что забыл перевести текст описания ошибки и втукать в модуль новую ресурсную строку или константу. Поэтому, раз времени не так и много осталось до завра, а завтра - снова в бой (на работу), покой нам только снится, то решил заняться именно работой над вспомогательным модулем. Назовем модуль, например GHelper...незнаю почему, но это первое, что пришло в голову.
Первая "проблема" с которой я столкнулся при работе с Google Data - это формат представления даты. Любая дата в Google API имеет следующий вид, например:
2006-01-23T16:28:05
Что соответствует RFC 3339 и означает:
23 января 2006 года время 16:28:05
После этой даты может стоять, например количество миллисекунд или часовой пояс или и то и другое вместе взятое. Наша цель - выделить дату и время. Первая функция преобразует время из формата RFC 3339 в формат Delphi:
function ServerDateToDateTime(cServerDate:string):TDateTime; var Year, Mounth, Day, hours, Mins, Seconds: Word; begin Year:=StrToInt(copy(cServerDate,1,4)); Mounth:=StrToInt(copy(cServerDate,6,2)); Day:=StrToInt(copy(cServerDate,9,2)); hours:=StrToInt(copy(cServerDate,12,2)); Mins:=StrToInt(copy(cServerDate,15,2)); Seconds:=StrToInt(copy(cServerDate,18,2)); Result:=EncodeDateTime(Year, Mounth, Day, hours, Mins, Seconds,0) end;
Вторая функция производит обратное преобразование (с учётом миллисекунд):
function DateTimeToServerDate(DateTime:TDateTime):string; var Year, Mounth, Day, hours, Mins, Seconds,MSec: Word; aYear, aMounth, aDay, ahours, aMins, aSeconds,aMSec: string; begin DecodeDateTime(DateTime,Year, Mounth, Day, hours, Mins, Seconds,MSec); aYear:=IntToStr(Year); if Mounth<10 then aMounth:='0'+IntToStr(Mounth) else aMounth:=IntToStr(Mounth); if Day<10 then aDay:='0'+IntToStr(Day) else aDay:=IntToStr(Day); if hours<10 then ahours:='0'+IntToStr(hours) else ahours:=IntToStr(hours); if Mins<10 then aMins:='0'+IntToStr(Mins) else aMins:=IntToStr(Mins); case MSec of 0..9:aMSec:='00'+IntToStr(MSec); 10..99:aMSec:='0'+IntToStr(MSec); else aMSec:=IntToStr(MSec); end; Result:=aYear+'-'+aMounth+'-'+aDay+'T'+ahours+':'+aMins+':'+aSeconds+'.'+aMSec+'Z'; end;
В принципе миллисекунда нам особо не важны, поэтому часть кода можно будет, в случае чего, убрать.
С этим вроде бы разобрались - теперь можно спокойно читать дату-время и перегонять из одного представления в другое. Двигаемся дальше. В Google Celendar API есть возможность назначать календарям определенный цвет. Причем цвет выбирается из чётко определенного набора из 21 цвета. Незаню как Вам, а мне лично будет лень каждый раз заглядывать в документацию с целью узнать какой цвет можно использовать, а какой нет. Поэтому создал небольшой массив-констант, где каждый элемент - доступный в Google API цвет в формате HEX:
GoogleColors: array [1..21]of string = ('A32929','B1365F','7A367A','5229A3', '29527A','2952A3','1B887A','28754E', '0D7813','528800','88880E','AB8B00', 'BE6D00','B1440E','865A5A','705770', '4E5D6C','5A6986','4A716C','6E6E41', '8D6F47');
В случае надобности, можно всегда перевести цвет из HEX в TColor и обратно двумя простыми функциями:
function HexToColor(Color: string): TColor; begin Result := RGB( StrToInt('$' + Copy(Color, 1, 2)), StrToInt('$' + Copy(Color, 3, 2)), StrToInt('$' + Copy(Color, 5, 2)) ); end;
function ColorToHex(Color: TColor): string; begin Result := IntToHex(GetRValue(Color), 2 ) + IntToHex(GetGValue(Color), 2 ) + IntToHex(GetBValue(Color), 2 ); end;
С цветами вроде бы тоже все понятно. В любой момент массив можно увеличить. Но это всё мелочи, по сравнению с последним набором констант,используемым в Google API - константы, используеые в Google Celendar API для определения часового пояса и местоположения пользователя. Всего в Google API используется 309 констант. Каждая константа определяет часовой пояс и местоположение. Я не стал долго мудрить, а просто нашел эти константы в исходнике HTML-странички настроек календаря и накидал процедурку, которая спарсит эти константы и представит в виде массива, где каждый элемент выглядит так:
('Pacific/Guadalcanal','(GMT+11:00) Гвадалканал','+11,00','')
то есть:
первый элемент - константа, используемая в протоколе Google Data
второй элемент - текстовое описание для пользователя
третий элемент - часовой пояс
четверты элемент - зарезервировал на всякий случай, например сейчас забил в этот элемент строку ru для определения того относится ли константа к России или нет.
Пользоваться каждый раз массивом на 309 строк...по-ходу будет гемморно. Поэтому решил немного поработать с TList. Вот, что у меня получилось в итоге (чур сильно не пинать, т.к. это мой первый опыт работы с TList :)):
type TTimeZone = packed record gConst: string; Desc : string; GMT: extended; rus: boolean; end; type PTimeZone = ^TTimeZone; type TTimeZoneList = class(TList) private procedure SetRecord(index: Integer; Ptr: PTimeZone); function GetRecord(index: Integer): PTimeZone; public constructor Create; procedure Clear; destructor Destroy; override; property TimeZone[i: Integer]: PTimeZone read GetRecord write SetRecord; end; procedure TTimeZoneList.Clear; var i: Integer; p: PTimeZone; begin for i := 0 to Pred(Count) do begin p := TimeZone[i]; if p <> nil then Dispose(p); end; inherited Clear; end; constructor TTimeZoneList.Create; var i:integer; Zone:PTimeZone; begin inherited Create; for i:=0 to High(GoogleTimeZones) do begin New(Zone); with Zone^ do begin gConst:=GoogleTimeZones[i,0]; Desc:=GoogleTimeZones[i,1]; GMT:=StrToFloat(GoogleTimeZones[i,2]); rus:=GoogleTimeZones[i,2]='rus'; end; Add(Zone); end; end; destructor TTimeZoneList.Destroy; begin Clear; inherited Destroy; end; function TTimeZoneList.GetRecord(index: Integer): PTimeZone; begin Result:= PTimeZone(Items[index]); end; procedure TTimeZoneList.SetRecord(index: Integer; Ptr: PTimeZone); var p: PTimeZone; begin p := TimeZone[index]; if p <> Ptr then begin if p <> nil then Dispose(p); Items[index] := Ptr; end; end;
Т.е. пока в список грузятся все константы из массива и при необходимости выбираются из списка требуемые данные. Попробовал использовать это "чудо в перьях" - вроде бы все работает нормально, хотя уверен тут можно что-нибудь и улучшить.
Вот примерно такое начало положено по работе с константами и данными Google API. Пока этого модуля должно хватить для работы с Календарем, поэтому в следующий раз продолжим разбирать Google Celendar API. А на сегодня все ;)
Каждый мужчина помима написания книги и т.д. должен построить дом. Специалисты из www.project-st.ru проектируют "Умные" Дома.
В прошлом посте я упоминал перчатки...сегодня предлагаю купить куртку аляску из Америки, ну или, если куртка есть, то здесь приобрести крутой ремень :)
---------------------------
| Делись! | Загружай! | Плюсуй! |
| | |









11 Фев 2010 в 10:30 пп
Гы, знакомое лицо на фотке :D
Нашёл кого вешать в программерский блог. Котов надо! :))))
11 Фев 2010 в 10:46 пп
Ах, да: помимо сисечек хотелось отметить ещё местами страшный код :) Например, DateTimeToServerDate можно было написать так:
12 Фев 2010 в 1:48 пп
По поводу картики…это человеческий облик Гугла для потенциальных рекламодателей :)
За «страшнй код» спасибо :) Всмысле спасибо, что не поленились выложить в коммент ещё один вариант функции более компактный и красивый.
16 Фев 2010 в 1:00 пп
ох, а девушка та какая шикарная, отвлекает немного от статьи, а так интересно:)