strftim () в sqlite дает неверные результаты - PullRequest
0 голосов
/ 19 февраля 2019

Я сохраняю поле date в базе данных как число секунд с начала эпохи:

enter image description here

Для отметки времени визображение (1550591783 - представляет 2019-02-19 19:26:23), sqlite должен возвращать 50 как день года, но возвращает 40.

Это запрос в PurchaseDao:

@Query("SELECT strftime('%j', date, 'unixepoch', 'localtime') AS day " +
       "FROM purchase " +
       "WHERE ...")
abstract List<Cost> getCosts();

и это преобразователь даты:

public class DateConverter {

    @TypeConverter
    public static Date fromTimestamp(Long value) {
        return value == null ? null : new Date(value * 1_000); // multiply by 1000 to make it milliseconds
    }

    @TypeConverter
    public static Long toTimestamp(Date date) {
        return date == null ? null : date.getTime() / 1_000; // divide by 1000 to store as seconds
    }
}

Даже если я передам now в качестве параметра для запроса (я даже применил его к свежему методу без каких-либо других отвлекающих факторов)Я получаю тот же неправильный результат:

@Query("SELECT strftime('%j', 'now', 'localtime')")

Я попытался удалить аргумент 'localtime', изменить преобразователи даты для сохранения даты в виде строки (например, в формате 2019-02-19) и запустить приложение вAVD, но я получаю один и тот же неправильный результат во всех случаях.

С другой стороны, когда я получаю день года с Календарем (Calendar.getInstance().get(Calendar.DAY_OF_YEAR);) или запускаю запросы на моем компьютере с помощью stetho, результаты верны.

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Может быть, это ошибка в реализации strftime"день года" где-то;Я получаю правильный результат.Если обновление SQLite или библиотек невозможно, возможно, вы можете обойти эту проблему, вычтя юлианский день первого января года дата из юлианского дня дата (упрощено и исправлено после комментариев):

SELECT cast (
       julianday(date, 'unixepoch', 'localtime') 
     - julianday(date, 'unixepoch', 'localtime', 'start of year')
     as int
     )
     + 1
from Purchase

Это, конечно, предполагает, что функция julianday работает нормально.

0 голосов
/ 11 марта 2019

как я уже объяснил здесь , преобразование времени UNIX работает примерно так:

SELECT DATE(dateColumn, 'unixepoch') AS isodate FROM tableName

или при хранении миллисекунд с начала эпохи, как это обычно бывает дляAndroid Java:

SELECT DATE(ROUND(dateColumn / 1000), 'unixepoch') AS isodate FROM tableName

это не требует умножения или деления в TypeConverter.в то время как этот операнд умножения / деления 1_000 в TypeConverter выглядит для меня странно.

проблема здесь может быть точно такой же, как с чистым SQL ... что date.getTime() / 1000 в 999/1000 случаевможет быть представлен только как значение float, а не как прямое целое значение long - если только не округлить это значение до long целочисленного значения.ROUND(dateColumn / 1000) предотвратит это с помощью SQL.почему-то этому вопросу не хватает контекста;Пожалуйста, прокомментируйте ниже, какую конкретную ценность вам нужно получить - и почему вам нужно ее получить;тогда я мог бы расширить свой ответ - потому что я не совсем понимаю цель получить день года для покупки.Я бы предпочел, чтобы с момента покупки прошло несколько дней.

...