mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-10 17:11:56 +01:00
Garmin: Fix all-day events
As per the CalendarContract, the begin timestamp corresponds to the UTC midnight-boundary of the start of the day. - Remove the redundant logic to truncate the date to the start of day - Remove the workaround for negative timezones (confirmed not workin with some EDT users) - Ensure birthdays also respect the UTC boundary - Offset the garmin timestamps by the UTC offset, ensuring they match midnight on the user's timezome (fixes all-day events offset by 1 day)
This commit is contained in:
parent
a46e970f84
commit
c628ce2c97
@ -28,16 +28,13 @@ import android.os.Handler;
|
|||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -234,15 +231,12 @@ public class CalendarReceiver extends ContentObserver {
|
|||||||
calendarEventSpec.timestamp = calendarEvent.getBeginSeconds();
|
calendarEventSpec.timestamp = calendarEvent.getBeginSeconds();
|
||||||
calendarEventSpec.durationInSeconds = calendarEvent.getDurationSeconds(); //FIXME: leads to problems right now
|
calendarEventSpec.durationInSeconds = calendarEvent.getDurationSeconds(); //FIXME: leads to problems right now
|
||||||
if (calendarEvent.isAllDay()) {
|
if (calendarEvent.isAllDay()) {
|
||||||
//force the all day events to begin at midnight and last N whole days
|
// As per the CalendarContract, for all-day events, the start timestamp is always in UTC
|
||||||
Calendar c = GregorianCalendar.getInstance();
|
// and corresponds to the midnight boundary
|
||||||
int numDays = (int) TimeUnit.DAYS.convert(calendarEvent.getEnd() - calendarEvent.getBegin(),
|
final int numDays = (int) TimeUnit.DAYS.convert(
|
||||||
TimeUnit.MILLISECONDS);
|
calendarEvent.getEnd() - calendarEvent.getBegin(),
|
||||||
c.setTimeInMillis(calendarEvent.getBegin());
|
TimeUnit.MILLISECONDS
|
||||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
);
|
||||||
//workaround for negative timezones
|
|
||||||
if (c.getTimeZone().getRawOffset() < 0) c.add(Calendar.DAY_OF_MONTH, 1);
|
|
||||||
calendarEventSpec.timestamp = (int) (c.getTimeInMillis() / 1000);
|
|
||||||
calendarEventSpec.durationInSeconds = 24 * 60 * 60 * numDays;
|
calendarEventSpec.durationInSeconds = 24 * 60 * 60 * numDays;
|
||||||
}
|
}
|
||||||
calendarEventSpec.description = calendarEvent.getDescription();
|
calendarEventSpec.description = calendarEvent.getDescription();
|
||||||
|
@ -41,6 +41,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.GFDI
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.ProtobufMessage;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.ProtobufMessage;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.status.ProtobufStatusMessage;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.status.ProtobufStatusMessage;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.CurrentPosition;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.CurrentPosition;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarEvent;
|
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarManager;
|
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarManager;
|
||||||
@ -212,11 +213,25 @@ public class ProtocolBufferHandler implements MessageHandler {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int startDateSeconds;
|
||||||
|
final int endDateSeconds;
|
||||||
|
|
||||||
|
if (mEvt.isAllDay()) {
|
||||||
|
// For all-day events, garmin expects the start and end date to match the midnight boundaries
|
||||||
|
// in the user's timezone. However, the calendar event will have them in the UTC timezone,
|
||||||
|
// so we need to convert it
|
||||||
|
startDateSeconds = (int) (DateTimeUtils.utcDateTimeToLocal(mEvt.getBegin()) / 1000);
|
||||||
|
endDateSeconds = (int) (DateTimeUtils.utcDateTimeToLocal(mEvt.getEnd()) / 1000);
|
||||||
|
} else {
|
||||||
|
startDateSeconds = mEvt.getBeginSeconds();
|
||||||
|
endDateSeconds = mEvt.getEndSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
final GdiCalendarService.CalendarService.CalendarEvent.Builder event = GdiCalendarService.CalendarService.CalendarEvent.newBuilder()
|
final GdiCalendarService.CalendarService.CalendarEvent.Builder event = GdiCalendarService.CalendarService.CalendarEvent.newBuilder()
|
||||||
.setTitle(mEvt.getTitle().substring(0, Math.min(mEvt.getTitle().length(), calendarServiceRequest.getMaxTitleLength())))
|
.setTitle(mEvt.getTitle().substring(0, Math.min(mEvt.getTitle().length(), calendarServiceRequest.getMaxTitleLength())))
|
||||||
.setAllDay(mEvt.isAllDay())
|
.setAllDay(mEvt.isAllDay())
|
||||||
.setStartDate(mEvt.getBeginSeconds())
|
.setStartDate(startDateSeconds)
|
||||||
.setEndDate(mEvt.getEndSeconds());
|
.setEndDate(endDateSeconds);
|
||||||
|
|
||||||
if (calendarServiceRequest.getIncludeLocation() && mEvt.getLocation() != null) {
|
if (calendarServiceRequest.getIncludeLocation() && mEvt.getLocation() != null) {
|
||||||
event.setLocation(mEvt.getLocation().substring(0, Math.min(mEvt.getLocation().length(), calendarServiceRequest.getMaxLocationLength())));
|
event.setLocation(mEvt.getLocation().substring(0, Math.min(mEvt.getLocation().length(), calendarServiceRequest.getMaxLocationLength())));
|
||||||
|
@ -140,8 +140,8 @@ public class DateTimeUtils {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Date dayStart(final LocalDate date) {
|
public static Date dayStartUtc(final LocalDate date) {
|
||||||
final Calendar calendar = Calendar.getInstance();
|
final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||||
calendar.set(Calendar.YEAR, date.getYear());
|
calendar.set(Calendar.YEAR, date.getYear());
|
||||||
calendar.set(Calendar.MONTH, date.getMonthValue() - 1);
|
calendar.set(Calendar.MONTH, date.getMonthValue() - 1);
|
||||||
calendar.set(Calendar.DAY_OF_MONTH, date.getDayOfMonth());
|
calendar.set(Calendar.DAY_OF_MONTH, date.getDayOfMonth());
|
||||||
@ -152,6 +152,20 @@ public class DateTimeUtils {
|
|||||||
return calendar.getTime();
|
return calendar.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long utcDateTimeToLocal(final long timestamp) {
|
||||||
|
final Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||||
|
utcCalendar.setTimeInMillis(timestamp);
|
||||||
|
final Calendar localCalendar = Calendar.getInstance(TimeZone.getDefault());
|
||||||
|
localCalendar.set(Calendar.YEAR, utcCalendar.get(Calendar.YEAR));
|
||||||
|
localCalendar.set(Calendar.MONTH, utcCalendar.get(Calendar.MONTH));
|
||||||
|
localCalendar.set(Calendar.DAY_OF_MONTH, utcCalendar.get(Calendar.DAY_OF_MONTH));
|
||||||
|
localCalendar.set(Calendar.HOUR_OF_DAY, utcCalendar.get(Calendar.HOUR_OF_DAY));
|
||||||
|
localCalendar.set(Calendar.MINUTE, utcCalendar.get(Calendar.MINUTE));
|
||||||
|
localCalendar.set(Calendar.SECOND, utcCalendar.get(Calendar.SECOND));
|
||||||
|
localCalendar.set(Calendar.MILLISECOND, utcCalendar.get(Calendar.MILLISECOND));
|
||||||
|
return localCalendar.getTimeInMillis();
|
||||||
|
}
|
||||||
|
|
||||||
public static Date dayEnd(final Date date) {
|
public static Date dayEnd(final Date date) {
|
||||||
final Calendar calendar = Calendar.getInstance();
|
final Calendar calendar = Calendar.getInstance();
|
||||||
calendar.setTime(date);
|
calendar.setTime(date);
|
||||||
|
@ -35,11 +35,13 @@ import java.time.format.DateTimeParseException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
@ -212,9 +214,13 @@ public class CalendarManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Follow the same logic as CalendarContract - all day events have the start
|
||||||
|
// timestamp at the UTC midnight boundary
|
||||||
|
final long startTimestampUtc = DateTimeUtils.dayStartUtc(birthday).getTime();
|
||||||
|
|
||||||
birthdays.add(new CalendarEvent(
|
birthdays.add(new CalendarEvent(
|
||||||
DateTimeUtils.dayStart(birthday).getTime(),
|
startTimestampUtc,
|
||||||
DateTimeUtils.dayStart(birthday).getTime() + 86400000L - 1L,
|
startTimestampUtc + 86400000L - 1L,
|
||||||
contactId.hashCode(),
|
contactId.hashCode(),
|
||||||
mContext.getString(R.string.contact_birthday, displayName),
|
mContext.getString(R.string.contact_birthday, displayName),
|
||||||
null,
|
null,
|
||||||
|
Loading…
Reference in New Issue
Block a user