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.widget.Toast;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Enumeration;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
@ -234,15 +231,12 @@ public class CalendarReceiver extends ContentObserver {
|
||||
calendarEventSpec.timestamp = calendarEvent.getBeginSeconds();
|
||||
calendarEventSpec.durationInSeconds = calendarEvent.getDurationSeconds(); //FIXME: leads to problems right now
|
||||
if (calendarEvent.isAllDay()) {
|
||||
//force the all day events to begin at midnight and last N whole days
|
||||
Calendar c = GregorianCalendar.getInstance();
|
||||
int numDays = (int) TimeUnit.DAYS.convert(calendarEvent.getEnd() - calendarEvent.getBegin(),
|
||||
TimeUnit.MILLISECONDS);
|
||||
c.setTimeInMillis(calendarEvent.getBegin());
|
||||
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);
|
||||
// As per the CalendarContract, for all-day events, the start timestamp is always in UTC
|
||||
// and corresponds to the midnight boundary
|
||||
final int numDays = (int) TimeUnit.DAYS.convert(
|
||||
calendarEvent.getEnd() - calendarEvent.getBegin(),
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
calendarEventSpec.durationInSeconds = 24 * 60 * 60 * numDays;
|
||||
}
|
||||
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.status.ProtobufStatusMessage;
|
||||
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.calendar.CalendarEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.calendar.CalendarManager;
|
||||
@ -212,11 +213,25 @@ public class ProtocolBufferHandler implements MessageHandler {
|
||||
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()
|
||||
.setTitle(mEvt.getTitle().substring(0, Math.min(mEvt.getTitle().length(), calendarServiceRequest.getMaxTitleLength())))
|
||||
.setAllDay(mEvt.isAllDay())
|
||||
.setStartDate(mEvt.getBeginSeconds())
|
||||
.setEndDate(mEvt.getEndSeconds());
|
||||
.setStartDate(startDateSeconds)
|
||||
.setEndDate(endDateSeconds);
|
||||
|
||||
if (calendarServiceRequest.getIncludeLocation() && mEvt.getLocation() != null) {
|
||||
event.setLocation(mEvt.getLocation().substring(0, Math.min(mEvt.getLocation().length(), calendarServiceRequest.getMaxLocationLength())));
|
||||
|
@ -140,8 +140,8 @@ public class DateTimeUtils {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Date dayStart(final LocalDate date) {
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
public static Date dayStartUtc(final LocalDate date) {
|
||||
final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
calendar.set(Calendar.YEAR, date.getYear());
|
||||
calendar.set(Calendar.MONTH, date.getMonthValue() - 1);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, date.getDayOfMonth());
|
||||
@ -152,6 +152,20 @@ public class DateTimeUtils {
|
||||
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) {
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
|
@ -35,11 +35,13 @@ import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
@ -212,9 +214,13 @@ public class CalendarManager {
|
||||
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(
|
||||
DateTimeUtils.dayStart(birthday).getTime(),
|
||||
DateTimeUtils.dayStart(birthday).getTime() + 86400000L - 1L,
|
||||
startTimestampUtc,
|
||||
startTimestampUtc + 86400000L - 1L,
|
||||
contactId.hashCode(),
|
||||
mContext.getString(R.string.contact_birthday, displayName),
|
||||
null,
|
||||
|
Loading…
Reference in New Issue
Block a user