[Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.21 07:58
Оценка: +1
Решил сначала тут проконсультироваться.

Проблема мутная.

Исходная задача.

В провайдере для EFCore нужно замапить операцию вычитания TimeOnly из TimeOnly:

И тут внезапно оказывается, что сервер (PG, Firebird) для операции:
select time '01:00:00' - time '03:00:00'

возвращает отрицательное значение -02:00:00.

А вычитание TimeOnly положительное: 22:00:00.

Ибо

/// <summary>
///  Gives the elapsed time between two points on a circular clock, which will always be a positive value.
/// </summary>
/// <param name="t1">The first TimeOnly instance.</param>
/// <param name="t2">The second TimeOnly instance..</param>
/// <returns>The elapsed time between t1 and t2.</returns>
public static TimeSpan operator -(TimeOnly t1, TimeOnly t2) => new TimeSpan((t1._ticks - t2._ticks + TimeSpan.TicksPerDay) % TimeSpan.TicksPerDay);


У меня собственно вопрос — зачем они тут против ветра?

Моя логика какая — если А<B, то (А-B)<0.

А логику реализации вычитания TimeOnly догнать не могу.

По моему — это тупо бага.

Вот они пишут "Gives the elapsed time between", ну так и возвращали бы TimeOnly.

А они возвращают interval (TimeSpan).

Что думаете?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: BlackEric http://black-eric.lj.ru
Дата: 06.10.21 08:28
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Что думаете?


Я бы спросил у них на гитхабе. Но отрицательного времени как бы нет. Поэтому такой вариант свою логику тоже имеет.
https://github.com/BlackEric001
Re: Аффинное пространство
От: Qbit86 Кипр
Дата: 06.10.21 08:31
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вот они пишут "Gives the elapsed time between", ну так и возвращали бы TimeOnly.

КД>А они возвращают interval (TimeSpan).

Это объекты семантически разных типов. TimeOnly или DateTime — это точки (разных) аффинных пространств, TimeSpan'ы — это векторы ассоциированного векторного пространства.
Если ты вычитаешь из точки точку, то ты получаешь не точку; ты получаешь вектор.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Аффинное пространство
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.21 08:36
Оценка:
Здравствуйте, Qbit86, Вы писали:

КД>>Вот они пишут "Gives the elapsed time between", ну так и возвращали бы TimeOnly.

КД>>А они возвращают interval (TimeSpan).

Q>Это объекты семантически разных типов. TimeOnly или DateTime — это точки (разных) аффинных пространств, TimeSpan'ы — это векторы ассоциированного векторного пространства.

Q>Если ты вычитаешь из точки точку, то ты получаешь не точку; ты получаешь вектор.

За каким Почему они этот вектор всегда делают положительным?

UPD. И называют точкой?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 06.10.2021 8:37 DDDX . Предыдущая версия .
Re[2]: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.21 08:38
Оценка:
Здравствуйте, BlackEric, Вы писали:

КД>>Что думаете?


BE>Я бы спросил у них на гитхабе.


https://github.com/dotnet/runtime/discussions/60056

КД>> Но отрицательного времени как бы нет. Поэтому такой вариант свою логику тоже имеет.


Дык они же возвращают не время (TimeOnly), а интервал (TimeSpan).
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Аффинное пространство
От: Qbit86 Кипр
Дата: 06.10.21 08:59
Оценка: +1 -1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>И называют точкой?


Они его не называют точкой. Просто в документации используют привычное перегруженное слово «время», которым человеки обозначают две сильно разные сущности: промежутки времени («два часа») и моменты времени («два часа дня»).

КД>Почему они этот вектор всегда делают положительным?


Решили реализовать семантику движения по 24-часовому циферблату Чтобы попасть из точки 3:00 в точку 1:00 нужно прождать 22 часа.
Если тебе нужна семантика направленного промежутка, то используй вычитание двух DateTime или DateTimeOffset.
Или вовсе перейди в ассоциированное векторное пространство, и вычитай два вектора TimeSpan, что в результате даёт опять вектор TimeSpan (направленный промежуток).
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: BlackEric http://black-eric.lj.ru
Дата: 06.10.21 09:31
Оценка: -1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, BlackEric, Вы писали:


КД>>>Что думаете?


BE>>Я бы спросил у них на гитхабе.


КД>https://github.com/dotnet/runtime/discussions/60056


КД>>> Но отрицательного времени как бы нет. Поэтому такой вариант свою логику тоже имеет.


КД>Дык они же возвращают не время (TimeOnly), а интервал (TimeSpan).


Интервал тем более не может быть отрицательным.
ЗЫ, если багу заведете, скиньте ссылку сюда, пожалуйста.
https://github.com/BlackEric001
Re[4]: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.21 09:55
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>Здравствуйте, BlackEric, Вы писали:


КД>>>>Что думаете?


BE>>>Я бы спросил у них на гитхабе.


КД>>https://github.com/dotnet/runtime/discussions/60056


КД>>>> Но отрицательного времени как бы нет. Поэтому такой вариант свою логику тоже имеет.


КД>>Дык они же возвращают не время (TimeOnly), а интервал (TimeSpan).


BE>Интервал тем более не может быть отрицательным.

Ну как это не может быть?

TimeSpan вполне может представлять отрицательное значение. И TimeOnly.Add(TimeSpan) вполне может принимать отрицательное значение.

Самое что интересное — оператора сложения TimeOnly+TimeSpan нет.

----
В TimeOnly есть еще интересный метод IsBetween

public bool IsBetween(TimeOnly start, TimeOnly end)

  Реализация
        /// <summary>
        /// Determines if a time falls within the range provided.
        /// Supports both "normal" ranges such as 10:00-12:00, and ranges that span midnight such as 23:00-01:00.
        /// </summary>
        /// <param name="start">The starting time of day, inclusive.</param>
        /// <param name="end">The ending time of day, exclusive.</param>
        /// <returns>True, if the time falls within the range, false otherwise.</returns>
        /// <remarks>
        /// If <paramref name="start"/> and <paramref name="end"/> are equal, this method returns false, meaning there is zero elapsed time between the two values.
        /// If you wish to treat such cases as representing one or more whole days, then first check for equality before calling this method.
        /// </remarks>
        public bool IsBetween(TimeOnly start, TimeOnly end)
        {
            long startTicks = start._ticks;
            long endTicks = end._ticks;


            return startTicks <= endTicks
                ? (startTicks <= _ticks && endTicks > _ticks)
                : (startTicks <= _ticks || endTicks > _ticks);
        }


"23:00:00".IsBetween("22:00:00","02:00:00") возвращет true.

----
Я вот думаю, зря они этот оператор вычитания добавили. Он только с толку будет сбивать.

Надо было вместо оператора метод делать. Типа

static TimeSpan Distance(TimeOnly, TimeOnly)


с поведением текущего вычитания.

BE>ЗЫ, если багу заведете, скиньте ссылку сюда, пожалуйста.


Ага.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Mihas  
Дата: 06.10.21 10:25
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>По моему — это тупо бага.

Мы тут недавно спорили о ценности типа TimeOnly. Вот, и проблемы с ним подоспели.
Re[4]: Аффинное пространство
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.21 10:44
Оценка:
Здравствуйте, Qbit86, Вы писали:

КД>>Почему они этот вектор всегда делают положительным?


Q>Решили реализовать семантику движения по 24-часовому циферблату Чтобы попасть из точки 3:00 в точку 1:00 нужно прождать 22 часа.


Да, скорее всего. Проблема в том, что зря они оператор вычитания для этих целей пристроили.

В SQL такая операция дает отрицательное значение.

Вот ты будешь писать linq запрос с выражением (timeOnlyValue1-timeOnlyValue2), что ты будешь ожидать?

Понятное дело, что "проблемы индейцев шерифа не волнуют", но "возможно будут проблемы".

Q>Если тебе нужна семантика направленного промежутка, то используй вычитание двух DateTime или DateTimeOffset.


Я вот думаю не предоставлять поддержку для этого оператора вычитания, а вместо него предлагать пару расширений TimeOnly:

// если a<b, то вернется отрицательное значение
static TimeSpan Subtract(this TimeOnly a, TimeOnly b);

и
//текущий оператор вычитания, у которого время течет только вперед.
static TimeSpan RemainedUntil(this TimeOnly a, TimeOnly b);


С английским у меня "не айс", так что названия наверное можно и получше сделать.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Teolog  
Дата: 07.10.21 08:23
Оценка:
КД>Что думаете?
Его нельзя использовать для сложения и вычитания, переход через полночь учитыватся криво.
Это не отметка времени, а синтетическое "время дня" для панели часов.
Хранить такое в базе имеет смысл, только если нужно знать не "когда произошло событие" а "в какое время рабочего дня произошло событие".
Re[4]: Аффинное пространство
От: v.a.v СССР  
Дата: 07.10.21 12:00
Оценка:
Здравствуйте, Qbit86, Вы писали:

КД>>Почему они этот вектор всегда делают положительным?


Q>Решили реализовать семантику движения по 24-часовому циферблату Чтобы попасть из точки 3:00 в точку 1:00 нужно прождать 22 часа.

Это правильно для смежных суток(но кто сказал что они смежные?). Такое неявное допущение может привести к ошибкам, которые выявятся уже при эксплуатации.
Правильнее было-бы выбрасывать исключение если "уменьшаемое" меньше "вычитаемого", и реализовать как метод, а не как оператор.
Re: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Kolesiki  
Дата: 07.10.21 12:16
Оценка: -2
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>select time '01:00:00' — time '03:00:00'

КД>возвращает отрицательное значение -02:00:00.

И это правильно!

КД>А вычитание TimeOnly положительное: 22:00:00.


А это — маразм. Добро пожаловать в логику мелкомягких брахмапутр! Как думают, так черех Жо и проектируют.
Re[2]: [Q] TimeOnly - TimeOnly --> всегда положительный TimeSpan
От: Mr.Delphist  
Дата: 07.10.21 12:47
Оценка:
Здравствуйте, Teolog, Вы писали:

T>Его нельзя использовать для сложения и вычитания, переход через полночь учитыватся криво.


А если ещё и переход между летним-зимним временем... мммм, вкусняшка.

T>Хранить такое в базе имеет смысл, только если нужно знать не "когда произошло событие" а "в какое время рабочего дня произошло событие".


Возможно, я покажусь ретроградом, но считаю что журналировать события надо всегда как дату + время. Все эти плюшки TimeOnly — это если надо сделать семантику "выбрать что-то внутри одного дня". Скажем, почасовой планировщик рабочих активностей.
Re[5]: Аффинное пространство
От: Ночной Смотрящий Россия  
Дата: 09.10.21 17:27
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>В SQL такая операция дает отрицательное значение.


В SQL нет аналога типа TimeOnly.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[4]: Аффинное пространство
От: Kolesiki  
Дата: 13.10.21 16:01
Оценка: -1
Здравствуйте, Qbit86, Вы писали:

КД>>Почему они этот вектор всегда делают положительным?


Q>Решили реализовать семантику движения по 24-часовому циферблату Чтобы попасть из точки 3:00 в точку 1:00 нужно прождать 22 часа.


С чего ты (за всех) решил, что программист хочет "попасть из точки 3 в точку 1"??
Здесь простая как тапок операция — ДВА ЧИСЛА. Пусть даже они обозначают точки во времени. Если запросили "1 — 3", это всегда -2. И чего ты там свои минуса кидаешь, болезный? Сам лажаешь, сам же криво объясняешь СВОЮ логику времени.

Это как раз типичная ошибка мелкомягких брахмапутр — "думать за всех", причём как им лично кажется правильным. На деле, вместо ОЖИДАЕМОГО правильного ответа они вкорячивают логику какого-то гика, который и программ-то ни разу не писал! Это второй косяк мелкомягкой банды — они пишут библиотеки, нихрена не делая в поле прикладных приложений. Как так можно проектировать?? Реальные кейсы использования нельзя придумать, ковыряя в носу перед белой доской из офиса компании.

Вот вместо своих тупых реклам *вбухивая миллионы) могли бы анонсировать общедоступные опросники: "Как вы считаете, что будет в результате (1 — 3)"? Больше б толку было.
Re[5]: Crossing midnight
От: Qbit86 Кипр
Дата: 13.10.21 22:41
Оценка: 6 (1) +1
Здравствуйте, Kolesiki, Вы писали:

K>С чего ты (за всех) решил, что программист хочет "попасть из точки 3 в точку 1"?


Это решил не я, а разработчики API для конкретных сценариев:

A TimeOnly is ideal for scenarios such as recurring meeting times, daily alarm clock times, or the times that a business opens and closes each day of the week.


A common operation with time-of-day values is to add or subtract some period of elapsed time. Unlike TimeSpan, a TimeOnly value will correctly handle such operations when crossing midnight. For example, an employee’s shift might start at 18:00 and last for 8 hours, ending at 02:00. TimeOnly will take care of that during the addition operation, and it also has an InBetween method that can easily be used to tell if any given time is within the worker’s shift.
https://devblogs.microsoft.com/dotnet/date-time-and-time-zone-enhancements-in-net-6/#the-timeonly-type


K>Если запросили "1 — 3", это всегда -2.


Для такой семантики уже существует тип TimeSpan, зачем делать его клон?

K>И чего ты там свои минуса кидаешь, болезный?


Здесь ты нагло злоупотребляешь неактивностью модераторов.

K>Это как раз типичная ошибка мелкомягких брахмапутр — "думать за всех", причём как им лично кажется правильным. На деле, вместо ОЖИДАЕМОГО правильного ответа они вкорячивают логику какого-то гика, который и программ-то ни разу не писал! Это второй косяк мелкомягкой банды — они пишут библиотеки, нихрена не делая в поле прикладных приложений. Как так можно проектировать?? Реальные кейсы использования нельзя придумать, ковыряя в носу перед белой доской из офиса компании.


Отсутствие у тебя фантазии и опыта не означает, что никто не сталкивался с «реальными кейсами». Я сталкивался. Например, нужно посчитать продолжительность «ночи» для пользователя, и попадает ли туда момент планируемой нотификации. Промежуток времени, когда пользователь обычно спит, задаётся началом и концом. В моём случае pre-net6.0 для этого используется TimeSpan, и нужны дополнительные приседания для обработки разных сценариев, когда промежуток захватывает полночь (23:30–07:30) или нет (01:00—09:00). В net6.0 это делается просто и естественно:
TimeOnly start = new(23, 30);
TimeOnly end = new(7, 30);
TimeSpan duration = end - start;
Console.WriteLine(duration.ToString()); // 08:00:00


K>вместо ОЖИДАЕМОГО правильного ответа


В этом примере ОЖИДАЕМЫЙ правильный ответ 08:00:00, а не -16:00:00.

Если же нужна семантика с «направленным расстоянием», то к ней всегда легко можно вернуться через timeOnly.ToTimeSpan().
TimeOnly start = new(23, 30);
TimeOnly end = new(7, 30);
TimeSpan duration = end.ToTimeSpan() - start.ToTimeSpan();
Console.WriteLine(duration.ToString()); // -16:00:00
Глаза у меня добрые, но рубашка — смирительная!
Отредактировано 13.10.2021 22:46 Qbit86 . Предыдущая версия . Еще …
Отредактировано 13.10.2021 22:44 Qbit86 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.