¿Cómo manejar las diferencias de la base de datos de zonas horarias de JodaTime y Android?

Quiero extender una discusión que comencé en la comunidad Reddit Android Devayer con una nueva pregunta: ¿Cómo administra una base de datos actualizada de zonas horarias que se envía con su aplicación utilizando la biblioteca JodaTime en un dispositivo que tiene información de zona horaria desactualizada?

El problema

El tema específico en cuestión se relaciona con una zona horaria particular, "Europa / Kaliningrado". Y puedo reproducir el problema: en un dispositivo Android 4.4, si configuro manualmente su zona horaria a la anterior, llamandonew DateTime() establecerá estoDateTime instancia a una hora una hora antes de la hora real que se muestra en la barra de estado del teléfono.

Creé una muestraActivity para ilustrar el problema En susonCreate() Yo llamo lo siguiente:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ResourceZoneInfoProvider.init(getApplicationContext());

    ViewGroup v = (ViewGroup) findViewById(R.id.root);
    addTimeZoneInfo("America/New_York", v);
    addTimeZoneInfo("Europe/Paris", v);
    addTimeZoneInfo("Europe/Kaliningrad", v);
}

private void addTimeZoneInfo(String id, ViewGroup root) {
    AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    am.setTimeZone(id);
    //Joda does not update its time zone automatically when there is a system change
    DateTimeZone.setDefault(DateTimeZone.forID(id));

    View v = getLayoutInflater().inflate(R.layout.info, root, false);

    TextView idInfo = (TextView) v.findViewById(R.id.id);
    idInfo.setText(id);

    TextView timezone = (TextView) v.findViewById(android.R.id.text1);
    timezone.setText("Time zone: " + TimeZone.getDefault().getDisplayName());

    TextView jodaTime = (TextView) v.findViewById(android.R.id.text2);
    //Using the same pattern as Date()
    jodaTime.setText("Time now (Joda): " + new DateTime().toString("EEE MMM dd HH:mm:ss zzz yyyy"));

    TextView javaTime = (TextView) v.findViewById(R.id.time_java);
    javaTime.setText("Time now (Java): " + new Date().toString());


    root.addView(v);
}

ResourceZoneInfoProvider.init() es parte deljoda-time-android biblioteca y está destinado a inicializar la base de datos de zona horaria de Joda.addTimeZoneInfo sobrescribe la zona horaria del dispositivo e infla una nueva vista donde se muestra la información actualizada de la zona horaria. Aquí hay un ejemplo de resultado:

Observe cómo para "Kaliningrado", Android lo asigna a "GMT + 3: 00" porque ese fue el caso hasta el 26 de octubre de 2014 (verArtículo de Wikipedia) Incluso algunos sitios web todavía muestran esta zona horaria como GMT + 3: 00 debido a lo relativamente reciente que es este cambio. Sin embargo, lo correcto es "GMT + 2: 00" como lo muestra JodaTime.

Posibles soluciones defectuosas?

Esto es un problema porque no importa cómo trate de eludirlo, al final, tengo que formatear el tiempo para mostrarlo al usuario en su zona horaria. Y cuando hago eso usando JodaTime, el tiempo se formateará incorrectamente porque no coincidirá con el tiempo esperado que se muestra el sistema.

Alternativamente, supongamos que manejo todo en UTC. Cuando el usuario agrega un evento en el calendario y elige una hora para el recordatorio, puedo configurarlo en UTC, guardarlo en el DB así y listo.

Sin embargo, necesito configurar ese recordatorio con AndroidAlarmManager no a la hora UTC convertí la hora establecida por el usuario, sino a la hora relativa a la hora en que desean que se active el recordatorio. Esto requiere que la información de zona horaria entre en juego.

Por ejemplo, si el usuario está en algún lugar en UTC + 1: 00 y establece un recordatorio para las 9:00 a.m., puedo:

Crear un nuevoDateTime instancia establecida para las 09:00 a.m. en la zona horaria del usuario y almacenar sus milisegundos en la base de datos. También puedo usar directamente los mismos milisegundos con elAlarmManager;Crear un nuevoDateTime instancia establecida para las 09:00 a.m. en UTC y almacenar sus milisegundos en la base de datos. Esto aborda mejor algunos otros problemas que no están exactamente relacionados con esta pregunta. Pero al establecer la hora con elAlarmManager, Necesito calcular su valor de milisegundos para las 09:00 am en la zona horaria del usuario;Ignora completamente a JodaDateTime y manejar la configuración del recordatorio usando Java'sCalendar. Esto hará que mi aplicación confíe en información de zona horaria desactualizada cuando muestre la hora, pero al menos no habrá inconsistencias al programar conAlarmManager o mostrando las fechas y horas.¿Qué me estoy perdiendo?

Puede que haya terminado de pensar esto y me temo que podría estar perdiendo algo obvio. Soy yo? ¿Hay alguna forma de que pueda seguir usando JodaTime en Android sin agregar mi propia administración de zona horaria a la aplicación e ignorar por completo todas las funciones de formateo de Android incorporadas?

Respuestas a la pregunta(4)

Su respuesta a la pregunta