После некоторого разбирательства с прогой удалось организовать импорт из ICAL-файлов и экспорт в оные. Но тут шеф захотел, чтобы был прямой контакт с CalDav через интернет. Я знаю, что на питоне такое возможно. На дельфине и даже Xojo (RealBasic) тоже - через спецбиблиотеку. Но как реализовать подключение к облачному сервису в Harbour/Minigui?
Отправлено: 16.07.21 20:52. Заголовок: Часовые пояса и зимнее/летнее время
И снова здравствуйте. Всё уже вроде работает, но проблема теперь с часовыми поясами. При импорте из онлайн-календаря в локальную базу данных получается так, что все даты сходят на время по Гринвичу. А у заказчика UTC+1 зимой и UTC+2 летом. Как сделать, чтобы при импорте правильно подхватывало зимнее/летнее время? Какая есть функция для определения время летнее или зимнее? По ключу TZID и потом ниже выходит какая-то дикая абракадабра.
lDts - Date Shift, я так понимаю. nUx - это какое-то астрономическое число, но что оно означает?
Тут идёт приплюсовка часа к времени, но как определить точно, это зимнее (от последнего воскресенья октября до последнего воскресенья марта) или летнее время?
но как определить точно, это зимнее (от последнего воскресенья октября до последнего воскресенья марта) или летнее время?
ф-я Gmt2Utc(...) определяет разницу gmt и местного времени. Определяйте сами запуская Gmt2Utc(NIL) хоть каждый час разницу зимнего или летнего времени. В показанном варианте ф-ии дата timestamp (gmt) строковая без разделителей, т.к. именно такая хранится в базе dbf для упрощения работы с индексами (данные получены из FireBird ф-ей nUx2cDts( nUx )). За месяц ~2 500 000 записей, базы годовые.
Отправлено: 26.07.21 12:56. Заголовок: hb_TSToUTC( ) e..
hb_TSToUTC( [<tLocalTime>] ) ➜ tUtcTime -> converts a local time tTIMESTAMP to UTC time. hb_DateTime() -> local time tTIMESTAMP
cDate - Utc время из базы тип char, значение без миллисекунд, т.е. '20201203102045' s_nHour - разница в часах локального времени и Utc времени, т.е. для нас: 3 - часа для летнего, 2 - для зимнего времени вычисляем при входе в программу и можно переустановить s_nHour в каком то режиме (по таймеру, каждый час) используется дальше как константа для отображения данных базы в локальном времени (в TsBrowse) и после GETBOX запросов периода дат, времени (локальное время задается), приводим ко времени Utc для работы с базой (SET SCOPE ..., SET FILTER ... и т.д.) lTrans используется для TsBrowse отображения в колонках или Label, если не задаем Picture Пример Скрытый текст
@ y, x LABEL Period VALUE ot:cPer+":" WIDTH oDlu:W1 HEIGHT h FONT "FormNorm" BACKCOLOR aBClr x += This.Period.Width @ y, x LABEL PerFrom VALUE ot:cPers WIDTH oDlu:W1 HEIGHT h FONT "FormNorm" BACKCOLOR aBClr CENTERALIGN x += This.PerFrom.Width + 2 @ y, x GETBOX PeriodFrom OBJ oGet WIDTH oDlu:D3 HEIGHT h VALUE CtoD("") ; ACTION {|| _wPost(5, , This.Name) } IMAGE "view" PICTURE Nil ; BUTTONWIDTH h FONT "FormNorm" BACKCOLOR BClr ; ON INIT {|og| og:lOnGotFocusSelect := .T. } oGet:OnF5 := {|og| _wPost(5, , og:cControlName) } // VK_F5 x += This.PeriodFrom.Width + 2 @ y, x LABEL PerTo VALUE ot:cPerp WIDTH oDlu:W1 HEIGHT h FONT "FormNorm" BACKCOLOR aBClr CENTERALIGN x += This.PerTo.Width + 2 @ y, x GETBOX PeriodTo OBJ oGet WIDTH oDlu:D3 HEIGHT h VALUE CtoD("") ; ACTION {|| _wPost(6, , This.Name) } IMAGE "view" PICTURE Nil ; BUTTONWIDTH h FONT "FormNorm" BACKCOLOR BClr ; ON INIT {|og| og:lOnGotFocusSelect := .T. } oGet:OnF5 := {|og| _wPost(6, , og:cControlName) } // VK_F5
y := This.Period.Row + This.Period.Height + nGh x := This.Period.Col @ y, x LABEL Times VALUE ot:cTime+":" WIDTH oDlu:W1 HEIGHT h FONT "FormNorm" BACKCOLOR aBClr x += This.Times.Width @ y, x LABEL TimeFrom VALUE ot:cPers WIDTH oDlu:W1 HEIGHT h FONT "FormNorm" BACKCOLOR aBClr CENTERALIGN x += This.TimeFrom.Width + 2 @ y, x GETBOX TimesFrom OBJ oGet WIDTH oDlu:D3 HEIGHT h VALUE space(6) ; PICTURE "@R 99:99:99" VALID {|og,hw2| bValid(og, hw2) } ; BUTTONWIDTH h FONT "FormNorm" BACKCOLOR BClr ; ON INIT {|og| og:lOnGotFocusSelect := .T. } x += This.TimesFrom.Width + 2 @ y, x LABEL TimeTo VALUE ot:cPerp WIDTH oDlu:W1 HEIGHT h FONT "FormNorm" BACKCOLOR aBClr CENTERALIGN x += This.TimeTo.Width + 2 @ y, x GETBOX TimesTo OBJ oGet WIDTH oDlu:D3 HEIGHT h VALUE space(6) ; PICTURE "@R 99:99:99" VALID {|og,hw2| bValid(og, hw2) } ; BUTTONWIDTH h FONT "FormNorm" BACKCOLOR BClr ; ON INIT {|og| og:lOnGotFocusSelect := .T. } ... :Event(10, {|ow,ky,cn| // OK button LOCAL o := Sys.Cargo, ot := Sys.Cargo:oBaseText LOCAL oObj := ow:Cargo:oObject, aTmp, cTmp, cDt1, cDt2, cFil, cObj LOCAL aObj := {}, cGm1 LOCAL aNam := {}, cGm2 LOCAL cNam := This.Events.Value LOCAL dDt1 := This.PeriodFrom.Value LOCAL dDt2 := This.PeriodTo.Value LOCAL cTm1 := This.TimesFrom.Value LOCAL cTm2 := This.TimesTo.Value LOCAL oBuf := oKeyData() oBuf:cOwn := "" oBuf:cObj := "" oBuf:cPer := "" oBuf:cTim := "" oBuf:lRowId := This.RowID.Value FOR EACH aTmp IN oObj:GetAll() ; AAdd(aObj, aTmp[1]) NEXT IF Empty(aObj) cObj := This.ObjNum.Value IF Empty(cObj) MsgStop("Empty objects !", "ERROR") This.ObjNum.SetFocus DO EVENTS RETURN Nil ELSE aObj := { Tr0(cObj, 12) } ENDIF ENDIF DO EVENTS IF Empty(dDt1) MsgStop("Period: Date error or empty date from !", "ERROR") This.PeriodFrom.SetFocus DO EVENTS RETURN Nil ENDIF IF Empty(dDt2) MsgStop("Period: Date error or empty date to !", "ERROR") This.PeriodTo.SetFocus DO EVENTS RETURN Nil ENDIF IF dDt1 > dDt2 MsgStop("Period: Date from > Date to !", "ERROR") This.PeriodFrom.SetFocus DO EVENTS RETURN Nil ENDIF cTm1 := left(trim(cTm1)+repl("0", 6), 6) cTm2 := left(trim(cTm2)+repl("0", 6), 6) cDt1 := hb_DtoC(dDt1, "YYYYMMDD")+cTm1 cDt2 := hb_DtoC(dDt2, "YYYYMMDD")+cTm2 lEmpty := Empty(Val(cTm1)) .and. Empty(Val(cTm2)) IF lEmpty cGm1 := Gmt2Utc(cDt1 , .F., .F.) cDt2 := hb_DtoC(dDt2+1, "YYYYMMDD")+cTm2 cGm2 := Gmt2Utc(cDt2 , .F., .F.) ELSE cGm1 := Gmt2Utc(cDt1, .F., .F.) cGm2 := Gmt2Utc(cDt2, .F., .F.) ENDIF cNam := trim(cNam) IF !Empty(cNam) FOR EACH cTmp IN hb_ATokens(cNam, ";") IF !Empty(cTmp) ; AAdd( aNam, upper(alltrim(cTmp)) ) ENDIF NEXT ENDIF IF Len(aObj) > 1 ; aObj := ASort(aObj) ENDIF oBuf:aObj := aClone(aObj) oBuf:cOwn := "" oBuf:cObj := "" oBuf:cPer := hb_DtoC(dDt1, "DD.MM.YYYY")+"."+" - "+hb_DtoC(dDt2, "DD.MM.YYYY")+"." IF !Empty(Val(cTm1)) .and. !Empty(Val(cTm2)) oBuf:cTim := Transform(cTm1, "@R 99:99:99")+" - "+Transform(cTm2, "@R 99:99:99") ENDIF oMain:StatusBar:Say(ot:cWait, 1) ; DO EVENTS cFil := Select_God( cGm1, cGm2, aObj, aNam, lEmpty ) oMain:StatusBar:Say("", 1) ; DO EVENTS IF !Empty(cFil) .and. hb_FileExists(cFil+".dbf") wSelectEvent(cFil, oBuf) ENDIF RETURN Nil }) ...
s_nHour - разница в часах локального времени и Utc времени, т.е. для нас: 3 - часа для летнего, 2 - для зимнего времени вычисляем при входе в программу
А как именно его вычисляют? Или всё же прописывают в файле INI?
Отправлено: 20.10.21 13:26. Заголовок: Итак, у меня всё, вр..
Итак, у меня всё, вроде работает, но вот у шефа с той же прогой файл listall_ics.xml, который должен использоваться для считывания данных из онлайн-календаря выдаёт такую вот хрень. Я так понимаю, это шеф неправильно ввёл свои имя пользователя и пароль.
<?xml version="1.0" encoding="utf-8"?> <d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns"> <s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception> <s:message>Username or password does not match</s:message> <s:sabredav-version>1.8.12</s:sabredav-version> </d:error>
Отправлено: 14.12.21 18:08. Заголовок: И снова здравствуйте..
И снова здравствуйте!
Там у шефа был пароль с запретным символом, попросил заменить, потом в условии фильтра немного порылся. Вроде, работает, но только на стационарных компах. Если событие онлайн-календаря вводят с телефона - жутко коверкает даты и время, кроме конечной даты. Стартовая дата всегда - 27 октября 1996 год. Время коверкает в обеих случаях. В чём разница между событием, введённым с компа и таковым с мобилки?
IF aCalStr[nBuf]="DTSTART" cDateTime:=SUBSTR(aCalStr[nBuf],AT(":",aCalStr[nBuf])+1) dStartDate:=STOD(LEFT(cDateTime,8)) cStartTime:=STRZERO(VAL(SUBSTR(cDateTime,10,2))+nTimeZone,2)+":"+SUBSTR(cDateTime,12,2)
Тут, как видите, в качестве разделителя используется двоеточие. Возможно, в мобильниках какой-то другой символ, но как это влияет на календарь?
Upd: с мобильника то же двоеточие, но даты искажаются до 1916, 1917 года. Upd2: в случае, если событие создано на андроидном мобильнике, но потом изменено и сохранено на компьютере - всё в порядке. Дата передаётся правильно, даже если меняют только текст.
Отправлено: 28.07.25 22:52. Заголовок: И вот, прошли года, ..
И вот, прошли года, всё вроде работает и тут только выяснилось, что он не импортирует старые события, которые 10 лет и старше. Интересно, это связано с ограничением размера переменной типа MEMO, куда считывает данные hb_memoread или с чем ещё может быть связано? Каков вообще максимальный размер переменной MEMO в оперативной памяти, не на диске? Надеюсь, до 2 терабайт там дело не дошло.
Все даты в формате GMT
3 час. Хитов сегодня: 200
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет