Azure Mobile Apps сохраняет неверную дату и время в базе данных Sqlite

#c# #sqlite #datetime #xamarin.forms #azure-mobile-services

#c# #sqlite #дата и время #xamarin.forms #azure-mobile-services

Вопрос:

Я пытаюсь сохранить объект с идентификатором и DateTimeOffset в базе данных AzureMobileServicesClient SQLite в приложении Xamarin Forms.

Это работает нормально, если временная метка не является неоднозначной. Когда мы переходим с летнего времени на стандартное, существует период времени, когда временная метка может быть неоднозначной в зависимости от часового пояса. В 2016 году в Дании это 2:00-3:00 утра 30 октября.

Я сохраняю объекты DateTimeOffset как UTC, но он сохраняет их как локальную временную метку.

Когда я сохраняю неоднозначную временную метку как 2016-10-30 12:30 0:00, она возвращается как 2016-10-30 11:30 0:00. Я тестировал это для других часовых поясов, и это происходит только с неоднозначным временем во время перехода с летнего времени на стандартное время в этом конкретном часовом поясе.

Я видел, что проблема исправлена для обычной базы данных SQLite здесь: http://www.thomaslevesque.com/2015/06/28/how-to-retrieve-dates-as-utc-in-sqlite /
Но поскольку я использую AzureMobileSerives, решение в этом случае не работает.

В этом коде я инициализирую AzureMobileService, сохраняю неоднозначную временную метку, а затем восстанавливаю ее снова и выписываю два раза на экран, чтобы увидеть разные выходные данные

 public static class SaveTimeStamp
{
    public static async Task Save()
    {
        //Init mobile service Client 
        var mobileService = new MobileServiceClient(Configuration.MobileAppsUrl);

        //init MobileService Database
        var dataStore = DependencyService.Get<IDataStore>();
        var path = dataStore.GetPath("store.db");
        dataStore.CreateFile(path);
        var store = new MobileServiceSQLiteStore(path);

        store.DefineTable<Entity>();
        await mobileService.SyncContext.InitializeAsync(store, StoreTrackingOptions.NotifyLocalAndServerOperations).ConfigureAwait(false);
        var entityTable = mobileService.GetSyncTable<Entity>();

        //Save entity with ambiguous timestamp
        var ambiguousTimestamp = new DateTimeOffset(2016, 10, 30, 0, 30, 0, TimeSpan.Zero); //UTC: 30th of October 12:30 AM   0:00 => DK time:30th of october 2:30 AM   2:00

        var entity = new Entity
        {
            Id = Guid.NewGuid().ToString(),
            Timestamp = ambiguousTimestamp
        };

        Debug.WriteLine("Saving datetime UTC: "   entity.Timestamp.UtcDateTime);

        await entityTable.InsertAsync(entity).ConfigureAwait(false);

        //Fetch saved entity
        var refecthedEntities = await entityTable.Where(e => e.Id == entity.Id).ToListAsync();
        var refecthedEntity = refecthedEntities.FirstOrDefault();

        if (refecthedEntity.Timestamp != ambiguousTimestamp)
        {
            Debug.WriteLine("Refecthed datetime UTC do not match: "   refecthedEntity.Timestamp.UtcDateTime);
        }
        else
        {
            Debug.WriteLine("Refecthed datetime UTC: "   refecthedEntity.Timestamp.UtcDateTime);
        }

        //output 
        //[0:]Saving datetime UTC: 10/30/2016 12:30:00 AM
        //[0:]Refecthed datetime UTC do not match: 10/29/2016 11:30:00 PM
    }
}

class Entity
{
    public string Id { get; set; }
    public DateTimeOffset Timestamp { get; set; }
}
  

Поскольку это приложение Xamarin, у меня также есть некоторый код в проекте xamarin.ios для инициализации базы данных.

 //IN Xamarin.IOS  
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {

        global::Xamarin.Forms.Forms.Init();
        Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); //Init Azure mobileservies on IOS Current  IOS 9.3
        SQLitePCL.CurrentPlatform.Init();

        LoadApplication(new App());

        App.ScreenWidth = (int)UIScreen.MainScreen.Bounds.Width;
        App.ScreenHeight = (int)UIScreen.MainScreen.Bounds.Height;

        return base.FinishedLaunching(app, options);
    }

    public override void WillEnterForeground(UIApplication uiApplication)
    {
        base.WillEnterForeground(uiApplication);
        uiApplication.IdleTimerDisabled = true;
    }

    public override void DidEnterBackground(UIApplication uiApplication)
    {
        base.DidEnterBackground(uiApplication);
        uiApplication.IdleTimerDisabled = false;
    }
}
  

Я попытался использовать DateTime вместо DateTimeOffset для объекта и использовать только DateTimeKind= UTC, но я получил тот же результат.

Комментарии:

1. Как вы храните дату и время? Как тики?

2. Это определяется платформой; класс entity имеет свойство Date типа DateTimeOffset . Когда я проверяю базу данных Sqlite, она сохраняется как количество секунд с момента некоторого смещения.

3. Верно, AsTicks действительно является настройкой по умолчанию. Просто хотел это проверить. У SQLite нет проблем с этим, так что это действительно проблема службы Azure.

4. У вас есть полный образец для совместного использования? Я хотел бы взглянуть в контексте.

5. В первом коде были некоторые ошибки, которые теперь исправлены. Класс SaveTimeStamp не является частью моего приложения, но я написал класс для выявления проблемы с сохранением неоднозначных временных меток. Я преобразовал SaveTimeStamp в статический, поэтому надеюсь, что он содержит достаточно информации для вас. Дайте мне знать, если вам нужно больше.

Ответ №1:

Это похоже на уже сообщенную ошибку: https://github.com/Azure/azure-mobile-apps-net-client/issues/131

Не стесняйтесь следить за ошибкой.

Комментарии:

1. Да, они связаны тем, что дата и время хранятся как локальные, а не UTC в клиентской базе данных Sqlite. Знаете ли вы, исправляется ли эта ошибка или когда можно ожидать исправления?

2. В настоящее время выпуск не запланирован. Я посмотрю на это в эти выходные и посмотрю, что с этим связано. Было бы полезно, если бы у вас был репозиторий GitHub с интерфейсом и серверной частью с минимальным воспроизведением. (В противном случае мне придется потратить время на ее создание). Если вы это сделаете, пожалуйста, добавьте это в проблему.

3. Извините, я использую мобильные приложения для приложения для клиента и не могу поместить все приложение в GitHub.

4. Понятно. Без корректного воспроизведения нам придется его сгенерировать. Это требует времени, что означает, что любое исправление будет отложено.