Merge lp:~renatofilho/qtorganizer5-eds/tz-support into lp:qtorganizer5-eds
- tz-support
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michael Sheldon |
Approved revision: | 48 |
Merged at revision: | 45 |
Proposed branch: | lp:~renatofilho/qtorganizer5-eds/tz-support |
Merge into: | lp:qtorganizer5-eds |
Diff against target: |
305 lines (+109/-35) 4 files modified
qorganizer/qorganizer-eds-engine.cpp (+55/-24) qorganizer/qorganizer-eds-engine.h (+2/-1) tests/unittest/event-test.cpp (+40/-0) tests/unittest/recurrence-test.cpp (+12/-10) |
To merge this branch: | bzr merge lp:~renatofilho/qtorganizer5-eds/tz-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Sheldon (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+213714@code.launchpad.net |
Commit message
Initial implementation of time zone support.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
- 46. By Renato Araujo Oliveira Filho
-
Fixed tzid set when time zone is null.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:46
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 47. By Renato Araujo Oliveira Filho
-
Fixed datetime conversion when using timezones.
Alan Pope πΊπ§π± π¦ (popey) wrote : | # |
Tested this on my desktop which has multiple calendars synced (personal and work) and all events (created by people in different timezones) appeared in the right place.
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
Are there any related MPs required for this MP to build/function as expected? NO
Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes): YES
Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator? YES
Did you successfully run all tests found in your component's Test Plan (https:/
If you changed the UI, was the change specified/approved by design? NO UI CHANGE
If you changed the packaging (debian), did you subscribe a core-dev to this MP? NO PACKAGE CHANGE
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:47
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 48. By Renato Araujo Oliveira Filho
-
Fixed failing test when running on devices with different time zone.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:48
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michael Sheldon (michael-sheldon) wrote : | # |
Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?
* Yes, synced events now display with correct timezone
Did CI run pass? If not, please explain why.
* Yes
Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
* Yes
- 49. By Renato Araujo Oliveira Filho
-
Fixed timezone name parse.
Preview Diff
1 | === modified file 'qorganizer/qorganizer-eds-engine.cpp' |
2 | --- qorganizer/qorganizer-eds-engine.cpp 2014-03-06 21:31:03 +0000 |
3 | +++ qorganizer/qorganizer-eds-engine.cpp 2014-04-03 21:15:35 +0000 |
4 | @@ -34,9 +34,8 @@ |
5 | |
6 | #include <QtCore/qdebug.h> |
7 | #include <QtCore/QPointer> |
8 | -#include <QtCore/qstringbuilder.h> |
9 | -#include <QtCore/quuid.h> |
10 | #include <QtCore/QCoreApplication> |
11 | +#include <QtCore/QTimeZone> |
12 | |
13 | #include <QtOrganizer/QOrganizerEventAttendee> |
14 | #include <QtOrganizer/QOrganizerItemLocation> |
15 | @@ -1094,10 +1093,37 @@ |
16 | change->emitSignals(this); |
17 | } |
18 | |
19 | -QDateTime QOrganizerEDSEngine::fromIcalTime(struct icaltimetype value) |
20 | -{ |
21 | - uint tmTime = icaltime_as_timet(value); |
22 | - return QDateTime::fromTime_t(tmTime); |
23 | +QDateTime QOrganizerEDSEngine::fromIcalTime(struct icaltimetype value, const char *tzId) |
24 | +{ |
25 | + uint tmTime; |
26 | + |
27 | + if (tzId) { |
28 | + QByteArray tzName(tzId); |
29 | + // keep only the timezone name. |
30 | + tzName = tzName.replace("/freeassociation.sourceforge.net/Tzfile/", ""); |
31 | + const icaltimezone *timezone = const_cast<const icaltimezone *>(icaltimezone_get_builtin_timezone(tzName.constData())); |
32 | + tmTime = icaltime_as_timet_with_zone(value, timezone); |
33 | + return QDateTime::fromTime_t(tmTime, QTimeZone(tzId)); |
34 | + } else { |
35 | + tmTime = icaltime_as_timet(value); |
36 | + return QDateTime::fromTime_t(tmTime); |
37 | + } |
38 | +} |
39 | + |
40 | +icaltimetype QOrganizerEDSEngine::fromQDateTime(const QDateTime &dateTime, |
41 | + bool allDay, |
42 | + QByteArray *tzId) |
43 | +{ |
44 | + |
45 | + if (dateTime.timeSpec() == Qt::TimeZone) { |
46 | + const icaltimezone *timezone = 0; |
47 | + *tzId = dateTime.timeZone().id(); |
48 | + timezone = const_cast<const icaltimezone *>(icaltimezone_get_builtin_timezone(tzId->constData())); |
49 | + return icaltime_from_timet_with_zone(dateTime.toTime_t(), allDay, timezone); |
50 | + } else { |
51 | + return icaltime_from_timet(dateTime.toTime_t(), allDay); |
52 | + } |
53 | + |
54 | } |
55 | |
56 | void QOrganizerEDSEngine::parseStartTime(ECalComponent *comp, QOrganizerItem *item) |
57 | @@ -1106,7 +1132,7 @@ |
58 | e_cal_component_get_dtstart(comp, dt); |
59 | if (dt->value) { |
60 | QOrganizerEventTime etr = item->detail(QOrganizerItemDetail::TypeEventTime); |
61 | - etr.setStartDateTime(fromIcalTime(*dt->value)); |
62 | + etr.setStartDateTime(fromIcalTime(*dt->value, dt->tzid)); |
63 | if (icaltime_is_date(*dt->value) != etr.isAllDay()) { |
64 | etr.setAllDay(icaltime_is_date(*dt->value)); |
65 | } |
66 | @@ -1121,7 +1147,7 @@ |
67 | e_cal_component_get_dtstart(comp, dt); |
68 | if (dt->value) { |
69 | QOrganizerTodoTime etr = item->detail(QOrganizerItemDetail::TypeTodoTime); |
70 | - etr.setStartDateTime(fromIcalTime(*dt->value)); |
71 | + etr.setStartDateTime(fromIcalTime(*dt->value, dt->tzid)); |
72 | if (icaltime_is_date(*dt->value) != etr.isAllDay()) { |
73 | etr.setAllDay(icaltime_is_date(*dt->value)); |
74 | } |
75 | @@ -1136,7 +1162,7 @@ |
76 | e_cal_component_get_dtend(comp, dt); |
77 | if (dt->value) { |
78 | QOrganizerEventTime etr = item->detail(QOrganizerItemDetail::TypeEventTime); |
79 | - etr.setEndDateTime(fromIcalTime(*dt->value)); |
80 | + etr.setEndDateTime(fromIcalTime(*dt->value, dt->tzid)); |
81 | if (icaltime_is_date(*dt->value) != etr.isAllDay()) { |
82 | etr.setAllDay(icaltime_is_date(*dt->value)); |
83 | } |
84 | @@ -1217,7 +1243,7 @@ |
85 | e_cal_component_get_rdate_list(comp, &periodList); |
86 | for(GSList *i = periodList; i != 0; i = i->next) { |
87 | ECalComponentPeriod *period = (ECalComponentPeriod*) i->data; |
88 | - QDateTime dt = fromIcalTime(period->start); |
89 | + QDateTime dt = fromIcalTime(period->start, 0); |
90 | dates.insert(dt.date()); |
91 | //TODO: period.end, period.duration |
92 | } |
93 | @@ -1235,7 +1261,7 @@ |
94 | e_cal_component_get_exdate_list(comp, &exdateList); |
95 | for(GSList *i = exdateList; i != 0; i = i->next) { |
96 | ECalComponentDateTime* dateTime = (ECalComponentDateTime*) i->data; |
97 | - QDateTime dt = fromIcalTime(*dateTime->value); |
98 | + QDateTime dt = fromIcalTime(*dateTime->value, dateTime->tzid); |
99 | dates.insert(dt.date()); |
100 | } |
101 | e_cal_component_free_exdate_list(exdateList); |
102 | @@ -1280,7 +1306,7 @@ |
103 | if (rule->count > 0) { |
104 | qRule.setLimit(rule->count); |
105 | } else { |
106 | - QDateTime dt = fromIcalTime(rule->until); |
107 | + QDateTime dt = fromIcalTime(rule->until, 0); |
108 | if (dt.isValid()) { |
109 | qRule.setLimit(dt.date()); |
110 | } else { |
111 | @@ -1346,7 +1372,7 @@ |
112 | e_cal_component_get_due(comp, &due); |
113 | if (due.value) { |
114 | QOrganizerTodoTime ttr = item->detail(QOrganizerItemDetail::TypeTodoTime); |
115 | - ttr.setDueDateTime(fromIcalTime(*due.value)); |
116 | + ttr.setDueDateTime(fromIcalTime(*due.value, due.tzid)); |
117 | if (icaltime_is_date(*due.value) != ttr.isAllDay()) { |
118 | ttr.setAllDay(icaltime_is_date(*due.value)); |
119 | } |
120 | @@ -1488,7 +1514,7 @@ |
121 | e_cal_component_get_dtstart(comp, &dt); |
122 | if (dt.value) { |
123 | QOrganizerJournalTime jtime; |
124 | - jtime.setEntryDateTime(fromIcalTime(*dt.value)); |
125 | + jtime.setEntryDateTime(fromIcalTime(*dt.value, dt.tzid)); |
126 | journal->saveDetail(&jtime); |
127 | } |
128 | e_cal_component_free_datetime(&dt); |
129 | @@ -1692,9 +1718,10 @@ |
130 | { |
131 | QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime); |
132 | if (!etr.isEmpty()) { |
133 | - struct icaltimetype ict = icaltime_from_timet(etr.startDateTime().toTime_t(), etr.isAllDay()); |
134 | + QByteArray tzId; |
135 | + struct icaltimetype ict = fromQDateTime(etr.startDateTime(), etr.isAllDay(), &tzId); |
136 | ECalComponentDateTime dt; |
137 | - dt.tzid = NULL; |
138 | + dt.tzid = tzId.isEmpty() ? NULL : tzId.constData(); |
139 | dt.value = &ict; |
140 | e_cal_component_set_dtstart(comp, &dt); |
141 | } |
142 | @@ -1704,9 +1731,10 @@ |
143 | { |
144 | QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime); |
145 | if (!etr.isEmpty()) { |
146 | - struct icaltimetype ict = icaltime_from_timet(etr.endDateTime().toTime_t(), etr.isAllDay()); |
147 | + QByteArray tzId; |
148 | + struct icaltimetype ict = fromQDateTime(etr.endDateTime(), etr.isAllDay(), &tzId); |
149 | ECalComponentDateTime dt; |
150 | - dt.tzid = NULL; |
151 | + dt.tzid = tzId.isEmpty() ? NULL : tzId.constData(); |
152 | dt.value = &ict; |
153 | e_cal_component_set_dtend(comp, &dt); |
154 | } |
155 | @@ -1716,9 +1744,10 @@ |
156 | { |
157 | QOrganizerTodoTime etr = item.detail(QOrganizerItemDetail::TypeTodoTime); |
158 | if (!etr.isEmpty()) { |
159 | - struct icaltimetype ict = icaltime_from_timet(etr.startDateTime().toTime_t(), etr.isAllDay()); |
160 | + QByteArray tzId; |
161 | + struct icaltimetype ict = fromQDateTime(etr.startDateTime(), etr.isAllDay(), &tzId); |
162 | ECalComponentDateTime dt; |
163 | - dt.tzid = NULL; |
164 | + dt.tzid = tzId.isEmpty() ? NULL : tzId.constData(); |
165 | dt.value = &ict; |
166 | e_cal_component_set_dtstart(comp, &dt);; |
167 | } |
168 | @@ -1888,9 +1917,10 @@ |
169 | { |
170 | QOrganizerTodoTime ttr = item.detail(QOrganizerItemDetail::TypeTodoTime); |
171 | if (!ttr.isEmpty()) { |
172 | - struct icaltimetype ict = icaltime_from_timet(ttr.dueDateTime().toTime_t(), ttr.isAllDay()); |
173 | + QByteArray tzId; |
174 | + struct icaltimetype ict = fromQDateTime(ttr.dueDateTime(), ttr.isAllDay(), &tzId); |
175 | ECalComponentDateTime dt; |
176 | - dt.tzid = NULL; |
177 | + dt.tzid = tzId.isEmpty() ? NULL : tzId.constData(); |
178 | dt.value = &ict; |
179 | e_cal_component_set_due(comp, &dt);; |
180 | } |
181 | @@ -2065,9 +2095,10 @@ |
182 | |
183 | QOrganizerJournalTime jtime = item.detail(QOrganizerItemDetail::TypeJournalTime); |
184 | if (!jtime.isEmpty()) { |
185 | - struct icaltimetype ict = icaltime_from_timet(jtime.entryDateTime().toTime_t(), FALSE); |
186 | + QByteArray tzId; |
187 | + struct icaltimetype ict = fromQDateTime(jtime.entryDateTime(), false, &tzId); |
188 | ECalComponentDateTime dt; |
189 | - dt.tzid = NULL; |
190 | + dt.tzid = tzId.isEmpty() ? NULL : tzId.constData(); |
191 | dt.value = &ict; |
192 | e_cal_component_set_dtstart(comp, &dt); |
193 | } |
194 | |
195 | === modified file 'qorganizer/qorganizer-eds-engine.h' |
196 | --- qorganizer/qorganizer-eds-engine.h 2014-02-25 17:12:32 +0000 |
197 | +++ qorganizer/qorganizer-eds-engine.h 2014-04-03 21:15:35 +0000 |
198 | @@ -190,7 +190,8 @@ |
199 | static void parseStatus(ECalComponent *comp, QtOrganizer::QOrganizerItem *item); |
200 | static void parseAttendeeList(ECalComponent *comp, QtOrganizer::QOrganizerItem *item); |
201 | |
202 | - static QDateTime fromIcalTime(struct icaltimetype value); |
203 | + static QDateTime fromIcalTime(struct icaltimetype value, const char *tzId); |
204 | + static icaltimetype fromQDateTime(const QDateTime &dateTime, bool allDay, QByteArray *tzId); |
205 | |
206 | static QtOrganizer::QOrganizerItem *parseEvent(ECalComponent *comp); |
207 | static QtOrganizer::QOrganizerItem *parseToDo(ECalComponent *comp); |
208 | |
209 | === modified file 'tests/unittest/event-test.cpp' |
210 | --- tests/unittest/event-test.cpp 2014-02-28 16:05:35 +0000 |
211 | +++ tests/unittest/event-test.cpp 2014-04-03 21:15:35 +0000 |
212 | @@ -512,6 +512,46 @@ |
213 | QOrganizerTodo newTodo = static_cast<QOrganizerTodo>(items[0]); |
214 | QCOMPARE(newTodo.startDateTime(), startDateTime); |
215 | } |
216 | + |
217 | + void testCreateWithDiffTimeZone() |
218 | + { |
219 | + static QString displayLabelValue = QStringLiteral("Event with diff timezone"); |
220 | + static QString descriptionValue = QStringLiteral("Event with diff timezone description"); |
221 | + static QDateTime startDateTime = QDateTime(QDate(2013, 9, 3), QTime(0, 30, 0), QTimeZone("Asia/Bangkok")); |
222 | + |
223 | + // create a new item |
224 | + QOrganizerTodo todo; |
225 | + todo.setCollectionId(m_collection.id()); |
226 | + todo.setStartDateTime(startDateTime); |
227 | + todo.setDisplayLabel(displayLabelValue); |
228 | + todo.setDescription(descriptionValue); |
229 | + |
230 | + QtOrganizer::QOrganizerManager::Error error; |
231 | + QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap; |
232 | + QList<QOrganizerItem> items; |
233 | + items << todo; |
234 | + bool saveResult = m_engine->saveItems(&items, |
235 | + QList<QtOrganizer::QOrganizerItemDetail::DetailType>(), |
236 | + &errorMap, |
237 | + &error); |
238 | + QVERIFY(saveResult); |
239 | + QCOMPARE(error, QOrganizerManager::NoError); |
240 | + QVERIFY(errorMap.isEmpty()); |
241 | + |
242 | + // query by the new item |
243 | + QOrganizerItemFetchHint hint; |
244 | + QList<QOrganizerItemId> ids; |
245 | + ids << items[0].id(); |
246 | + items = m_engine->items(ids, hint, &errorMap, &error); |
247 | + QCOMPARE(items.count(), 1); |
248 | + |
249 | + // compare start datetime |
250 | + QOrganizerTodo newTodo = static_cast<QOrganizerTodo>(items[0]); |
251 | + QDateTime newStartDateTime = newTodo.startDateTime(); |
252 | + QCOMPARE(newStartDateTime.timeSpec(), Qt::TimeZone); |
253 | + QCOMPARE(newStartDateTime.timeZone(), QTimeZone("Asia/Bangkok")); |
254 | + QCOMPARE(newTodo.startDateTime(), startDateTime); |
255 | + } |
256 | }; |
257 | |
258 | const QString EventTest::defaultCollectionName = QStringLiteral("TEST_EVENT_COLLECTION"); |
259 | |
260 | === modified file 'tests/unittest/recurrence-test.cpp' |
261 | --- tests/unittest/recurrence-test.cpp 2014-03-06 21:31:03 +0000 |
262 | +++ tests/unittest/recurrence-test.cpp 2014-04-03 21:15:35 +0000 |
263 | @@ -160,11 +160,13 @@ |
264 | { |
265 | static QString displayLabelValue = QStringLiteral("Monthly test"); |
266 | static QString descriptionValue = QStringLiteral("Monthly description"); |
267 | + static QDateTime eventStartDate = QDateTime(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC); |
268 | + static QDateTime eventEndDate = QDateTime(QDate(2013, 1, 1), QTime(0, 30, 0), Qt::UTC); |
269 | |
270 | QOrganizerEvent ev; |
271 | ev.setCollectionId(m_collection.id()); |
272 | - ev.setStartDateTime(QDateTime(QDate(2013, 1, 1), QTime(0,0,0))); |
273 | - ev.setEndDateTime(QDateTime(QDate(2013, 1, 1), QTime(0,30,0))); |
274 | + ev.setStartDateTime(eventStartDate); |
275 | + ev.setEndDateTime(eventEndDate); |
276 | ev.setDisplayLabel(displayLabelValue); |
277 | ev.setDescription(descriptionValue); |
278 | |
279 | @@ -192,19 +194,19 @@ |
280 | QOrganizerItemFetchHint hint; |
281 | QOrganizerItemFilter filter; |
282 | items = m_engine->items(filter, |
283 | - QDateTime(QDate(2013, 1, 1), QTime(0,0,0)), |
284 | - QDateTime(QDate(2014, 1, 1), QTime(0,0,0)), |
285 | - 100, |
286 | - sort, |
287 | - hint, |
288 | - &error); |
289 | + eventStartDate, |
290 | + eventStartDate.addYears(1), |
291 | + 100, |
292 | + sort, |
293 | + hint, |
294 | + &error); |
295 | QCOMPARE(items.count(), 24); |
296 | for(int i=0; i < 12; i++) { |
297 | QOrganizerEventTime time = items[i*2].detail(QOrganizerItemDetail::TypeEventTime); |
298 | - QCOMPARE(time.startDateTime(), QDateTime(QDate(2013, i+1, 1), QTime(0,0,0))); |
299 | + QCOMPARE(time.startDateTime(), eventStartDate.addMonths(i)); |
300 | |
301 | time = items[(i*2)+1].detail(QOrganizerItemDetail::TypeEventTime); |
302 | - QCOMPARE(time.startDateTime(), QDateTime(QDate(2013, i+1, 5), QTime(0,0,0))); |
303 | + QCOMPARE(time.startDateTime(), QDateTime(QDate(2013, i+1, 5), QTime(0,0,0), Qt::UTC)); |
304 | } |
305 | } |
306 |
FAILED: Continuous integration, rev:45 jenkins. qa.ubuntu. com/job/ qtorganizer5- eds-ci/ 122/ jenkins. qa.ubuntu. com/job/ qtorganizer5- eds-trusty- amd64-ci/ 111/console jenkins. qa.ubuntu. com/job/ qtorganizer5- eds-trusty- armhf-ci/ 109/console jenkins. qa.ubuntu. com/job/ qtorganizer5- eds-trusty- i386-ci/ 109/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtorganizer 5-eds-ci/ 122/rebuild
http://