Fix all day date synchronization

pull/1336/head
Alex Baker 5 years ago
parent cb0823205a
commit 5ff6b885f7

@ -9,6 +9,7 @@ import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.tasks.R
import org.tasks.TestUtilities.withTZ
import org.tasks.caldav.iCalendar.Companion.getParent
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS
@ -22,10 +23,13 @@ import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT
import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.TaskMaker
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.RRULE
import org.tasks.makers.TaskMaker.newTask
import org.tasks.preferences.Preferences
import org.tasks.time.DateTime
import java.util.*
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -169,7 +173,121 @@ class OpenTasksSynchronizerTest : InjectingTestCase() {
assertEquals("1234", openTaskDao.getTask(listId.toLong(), "abcd")?.task?.getParent())
}
@Test
fun readDueDatePositiveOffset() = runBlocking {
val (listId, list) = openTaskDao.insertList()
openTaskDao.insertTask(listId, ALL_DAY_DUE)
withTZ(BERLIN) {
synchronizer.sync()
}
val caldavTask = caldavDao.getTaskByRemoteId(list.uuid!!, "3863299529704302692")
val task = taskDao.fetch(caldavTask!!.task)
assertEquals(
DateTime(2021, 2, 1, 12, 0, 0, 0, BERLIN).millis,
task?.dueDate
)
}
@Test
fun writeDueDatePositiveOffset() = withTZ(BERLIN) {
val (listId, list) = openTaskDao.insertList()
val taskId = taskDao.createNew(newTask(
with(TaskMaker.DUE_DATE, DateTime(2021, 2, 1))
))
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "1234"),
with(TASK, taskId)
))
synchronizer.sync()
assertEquals(
1612137600000,
openTaskDao.getTask(listId.toLong(), "1234")?.task?.due?.date?.time
)
}
@Test
fun readDueDateNoOffset() = runBlocking {
val (listId, list) = openTaskDao.insertList()
openTaskDao.insertTask(listId, ALL_DAY_DUE)
withTZ(LONDON) {
synchronizer.sync()
}
val caldavTask = caldavDao.getTaskByRemoteId(list.uuid!!, "3863299529704302692")
val task = taskDao.fetch(caldavTask!!.task)
assertEquals(
DateTime(2021, 2, 1, 12, 0, 0, 0, LONDON).millis,
task?.dueDate
)
}
@Test
fun writeDueDateNoOffset() = withTZ(LONDON) {
val (listId, list) = openTaskDao.insertList()
val taskId = taskDao.createNew(newTask(
with(TaskMaker.DUE_DATE, DateTime(2021, 2, 1))
))
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "1234"),
with(TASK, taskId)
))
synchronizer.sync()
assertEquals(
1612137600000,
openTaskDao.getTask(listId.toLong(), "1234")?.task?.due?.date?.time
)
}
@Test
fun readDueDateNegativeOffset() = runBlocking {
val (listId, list) = openTaskDao.insertList()
openTaskDao.insertTask(listId, ALL_DAY_DUE)
withTZ(NEW_YORK) {
synchronizer.sync()
}
val caldavTask = caldavDao.getTaskByRemoteId(list.uuid!!, "3863299529704302692")
val task = taskDao.fetch(caldavTask!!.task)
assertEquals(
DateTime(2021, 2, 1, 12, 0, 0, 0, NEW_YORK).millis,
task?.dueDate
)
}
@Test
fun writeDueDateNegativeOffset() = withTZ(NEW_YORK) {
val (listId, list) = openTaskDao.insertList()
val taskId = taskDao.createNew(newTask(
with(TaskMaker.DUE_DATE, DateTime(2021, 2, 1))
))
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "1234"),
with(TASK, taskId)
))
synchronizer.sync()
assertEquals(
1612137600000,
openTaskDao.getTask(listId.toLong(), "1234")?.task?.due?.date?.time
)
}
companion object {
val BERLIN = TimeZone.getTimeZone("Europe/Berlin")
val LONDON = TimeZone.getTimeZone("Europe/London")
val NEW_YORK = TimeZone.getTimeZone("America/New_York")
val SUBTASK = """
BEGIN:VCALENDAR
VERSION:2.0
@ -184,5 +302,20 @@ class OpenTasksSynchronizerTest : InjectingTestCase() {
END:VTODO
END:VCALENDAR
""".trimIndent()
val ALL_DAY_DUE = """
BEGIN:VCALENDAR
VERSION:2.0
PRODID:+//IDN tasks.org//android-110304//EN
BEGIN:VTODO
DTSTAMP:20210129T155402Z
UID:3863299529704302692
CREATED:20210129T155318Z
LAST-MODIFIED:20210129T155329Z
SUMMARY:Due date
DUE;VALUE=DATE:20210201
END:VTODO
END:VCALENDAR
""".trimIndent()
}
}

@ -3,6 +3,7 @@ package org.tasks
import android.content.Context
import at.bitfire.ical4android.Task.Companion.tasksFromReader
import com.todoroo.astrid.data.Task
import kotlinx.coroutines.runBlocking
import org.tasks.caldav.CaldavConverter
import org.tasks.data.CaldavTask
import org.tasks.preferences.Preferences
@ -13,13 +14,15 @@ import java.nio.file.Paths
import java.util.*
object TestUtilities {
fun withTZ(id: String, runnable: () -> Unit) = withTZ(TimeZone.getTimeZone(id), runnable)
fun withTZ(id: String, runnable: suspend () -> Unit) = withTZ(TimeZone.getTimeZone(id), runnable)
fun withTZ(tz: TimeZone, runnable: () -> Unit) {
fun withTZ(tz: TimeZone, runnable: suspend () -> Unit) {
val def = TimeZone.getDefault()
try {
TimeZone.setDefault(tz)
runnable()
runBlocking {
runnable()
}
} finally {
TimeZone.setDefault(def)
}

@ -82,12 +82,12 @@ public class CaldavConverter {
long startDate = task.hasStartTime() ? task.getHideUntil() : startOfDay(task.getHideUntil());
if (dueDate > 0) {
startDate = Math.min(dueDate, startDate);
remote.setDue(new Due(allDay ? new Date(dueDate) : getDateTime(dueDate)));
remote.setDue(new Due(allDay ? getDate(dueDate) : getDateTime(dueDate)));
} else {
remote.setDue(null);
}
if (startDate > 0) {
remote.setDtStart(new DtStart(allDay ? new Date(startDate) : getDateTime(startDate)));
remote.setDtStart(new DtStart(allDay ? getDate(startDate) : getDateTime(startDate)));
} else {
remote.setDtStart(null);
}
@ -121,6 +121,10 @@ public class CaldavConverter {
iCalendar.Companion.setParent(remote, task.getParent() == 0 ? null : caldavTask.getRemoteParent());
}
private static Date getDate(long timestamp) {
return new Date(timestamp + newDateTime(timestamp).getOffset());
}
private static DateTime getDateTime(long timestamp) {
net.fortuna.ical4j.model.TimeZone tz =
DateUtils.INSTANCE.ical4jTimeZone(TimeZone.getDefault().getID());

@ -26,8 +26,6 @@ import org.tasks.time.DateTime.UTC
import timber.log.Timber
import java.io.ByteArrayOutputStream
import java.io.StringReader
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import javax.inject.Inject
@ -162,7 +160,6 @@ class iCalendar @Inject constructor(
}
companion object {
private val DUE_DATE_FORMAT = SimpleDateFormat("yyyyMMdd", Locale.US)
private const val APPLE_SORT_ORDER = "X-APPLE-SORT-ORDER"
private val IS_PARENT = { r: RelatedTo ->
r.parameters.getParameter<RelType>(Parameter.RELTYPE).let {
@ -198,21 +195,14 @@ class iCalendar @Inject constructor(
@JvmStatic
fun getLocal(property: DateProperty): Long {
val dateTime = if (property.date is DateTime) {
val dateTime: org.tasks.time.DateTime? = if (property.date is DateTime) {
val dt = property.date as DateTime
org.tasks.time.DateTime(
dt.time,
dt.timeZone ?: if (dt.isUtc) UTC else TimeZone.getDefault()
)
} else {
try {
DUE_DATE_FORMAT.parse(property.value)?.let {
org.tasks.time.DateTime(it)
}
} catch (e: ParseException) {
Timber.e(e)
null
}
org.tasks.time.DateTime(property.date.time).let { it.minusMillis(it.offset) }
}
return dateTime?.toLocal()?.millis ?: 0
}

@ -277,7 +277,7 @@ public class DateTime {
return subtract(Calendar.MINUTE, minutes);
}
public DateTime minusMillis(int millis) {
public DateTime minusMillis(long millis) {
return new DateTime(timestamp - millis, timeZone);
}

Loading…
Cancel
Save