Локализация дат и в распределенных приложениях
От: baranovda Российская Империя  
Дата: 24.03.15 21:55
Оценка:
Думаю, Sciter тут представлять не надо и его все знают.

Есть в нем закавыка с контролом ввода даты.
В форме ввода я выбираю дату при помощи выпадающего календаря, далее эта дата заворачивается в JSON и отправляется на веб-сервер.
На веб-сервере я обнаруживаю, что получаю не ту дату, которую вводил, а UTC, то есть минус три часа поправки на мой часовой пояс, или иными словами не 25.03.2015, а 24.03.2015 21:00.
То есть контрол сам поправил введенную мной дату и привел ее к UTC.

Академически все правильно: Андрей считает, что в распределенных приложениях, которые могут работать с сервером откуда угодно, дату/время нужно приводить к UTC и я в этом с ним согласен.

Должен ли такое преобразование самостоятельно выполнять контрол, работающий в Presentation Layer?
Или же это ответственность Buisness Layer-а (контроллера, презентера или чего там еще)?

Т.е. я считаю, что я, если хочу, должен перед отправкой JSON на сервер самостоятельно внести коррекцию TimeZone во все даты в JavaScript/TIScript-контроллере, или как-то передать веб-серверу TimeZone клиента (через Cookie, через сессию, или вообще вынести настройку TimeZone пользователя в профиль пользователя, хранящийся в базе данных).

Кто прав?
Отредактировано 24.03.2015 21:56 α . Предыдущая версия .
Re: Локализация дат и в распределенных приложениях
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.03.15 23:41
Оценка: +1
Здравствуйте, baranovda, Вы писали:

B>Кто прав?


Оба неправы.
Дата (без времени) не должна преобразовываться вообще.

ДатаВремя в явном виде должна передаваться с timezone (datetimeoffset), коррекция только при выводе если необходимо (tolocaltime).
Если человек вводит дату\время локально, то нужно определять (передавать на клиент) таймзону по географии. Если невозможно, то хранить в профиле.
Re: Локализация дат и в распределенных приложениях
От: c-smile Канада http://terrainformatica.com
Дата: 25.03.15 00:14
Оценка: +2
Здравствуйте, baranovda, Вы писали:

B>Думаю, Sciter тут представлять не надо и его все знают.


B>Есть в нем закавыка с контролом ввода даты.

B>В форме ввода я выбираю дату при помощи выпадающего календаря, далее эта дата заворачивается в JSON и отправляется на веб-сервер.
B>На веб-сервере я обнаруживаю, что получаю не ту дату, которую вводил, а UTC, то есть минус три часа поправки на мой часовой пояс, или иными словами не 25.03.2015, а 24.03.2015 21:00.
B>То есть контрол сам поправил введенную мной дату и привел ее к UTC.

B>Академически все правильно: Андрей считает, что в распределенных приложениях, которые могут работать с сервером откуда угодно, дату/время нужно приводить к UTC и я в этом с ним согласен.


B>Должен ли такое преобразование самостоятельно выполнять контрол, работающий в Presentation Layer?

B>Или же это ответственность Buisness Layer-а (контроллера, презентера или чего там еще)?

Я честно говоря не понимаю твою проблему...
Мне кажется ты как-то неправильно это все интерпретируешь.

Дано:
1. Sciter у которого есть тип Date который хранит UTC дату и время. Как и в JavaScript.
2. Есть <input|date> и <input|time> у которых value тоже Date.
3. Эти inputs показывают дату (UTC) с учетом текущей timezone пользователя (есть возможность задать любую timezone но это не важно в данном случае).

Ну вот какие проблемы с этим:
var birthday = $(input[type=date]);
// Values that user sees:
// birthday.value.day 
// birthday.value.month 
// birthday.value.year
// Also available 
// birthday.value.UTCday 
// birthday.value.UTCmonth 
// birthday.value.UTCyear

?

То как ты кодируешь дату или время при JSON передаче абсолютно не релевантно. Это функция твоего контроллера который стоит между моделью данных и view.
JSON не специфицирует никак даты — т.е. это сугубо твой бизнес. Приведи свои форматы дат к Date (UTC) при отправке и получении JSON от сервера и проблемы нет.

И в общем случае сервер обязан хранить даты событий в UTC.
Отредактировано 25.03.2015 0:28 c-smile . Предыдущая версия .
Re: Локализация дат и в распределенных приложениях
От: C0s Россия  
Дата: 25.03.15 00:27
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Должен ли


я думаю, что бизнес-слой должен помогать слою презентации с тайм-зоной, т.е. либо её "угадывать" для плохо профилированного пользователя, либо "почти принудительно подставлять" для хорошо-профилированного пользователя

при этом слой презентации должен отвечать за передачу на бизнес-слой полного времени, т.е. с указанием TZ, при этом TZ подставляется либо автоматически, но наглядно для пользователя через ту самую помощь бизнес-слоя, либо вручную, т.к. пользователю даётся возможность её указать.

хранение времени на backend'е нагляднее всего делается такими типами как oracle timestamp with tz — по ним суппорт, работающий на уровне БД, видит всё сразу без необходимости арифметизировать головой, при этом вся арифметика и сравнение поддержано БД на своём уровне
Re[2]: Локализация дат и в распределенных приложениях
От: c-smile Канада http://terrainformatica.com
Дата: 25.03.15 00:54
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Дата (без времени) не должна преобразовываться вообще.


Как-то уж слишком категорично-оптимистично.

Скажем такая безобидная вещь как "день рождения"... я у себя на West Coast (UTC -8) ввожу её в систему.
И сервер, скажем, в Японии (UTC +9) сконфигурирован на посыл поздравлений по утру клиента.

Как это сделать без TZ?

Это я к тому что даже "просто дата" должна в общем случае храниться в системе с timezone.
Re[2]: Локализация дат и в распределенных приложениях
От: baranovda Российская Империя  
Дата: 25.03.15 06:57
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Я честно говоря не понимаю твою проблему...

CS>Мне кажется ты как-то неправильно это все интерпретируешь.
CS>То как ты кодируешь дату или время при JSON передаче абсолютно не релевантно. Это функция твоего контроллера который стоит между моделью данных и view.

Попробую на пальцах

  Пример (рядом нужно положить plus.tis и plus.css):
<html>
<head>
<style>
@import url(plus.css);
</style>
<script type="text/tiscript">
  include "plus.tis";
  
  var Model = {
    date: new Date();
  }
  
  function self#test1.onClick()
  {  
     view.msgbox(#alert, self#date.value);
  }
  
  function self#test2.onClick()
  {  
     view.msgbox(#alert, String.printf("%v", Model));
  }
  
  function self#test3.onClick()
  {  
     var d = new Date("2015-03-24T21:00:00");
     view.msgbox(#alert, Date.timeZoneOffset());
     d.millisecond += Date.timeZoneOffset();
     view.msgbox(#alert, d.toLocaleString());
     Model.date = d;
  }

</script>
</head>
<body>
  <form model="Model">
    Case date: <input type="date" name="date" id="date" />
  </form>
  
  <div model="Model">
    Date: <output name="date" type="date"/> Time: <output name="date" type="time"/>
  </div>
  
  <button id="test1">Show control date</button>
  <button id="test2">Show JSON</button>
  <button id="test3">Set date</button>
</body>
</html>


a) Ввожу дату — 25.03.2015
б) На сервер приходит 2015-03-25T21:00:00 (UTC). Я эту дату сохраняю в базу
в) Теперь клиент перезапрашивает данные и мне нужно эту дату отрисовать например в <table>.
в.1) Сервер отдает дату, хранящуюся в базе данных as is. Выполним в Sciter self#date.value = new Date("2015-03-24T21:00:00"). В datepicker-е рисуется 24.03.2015
в.2) Сервер должен отдать клиенту дату с учетом клиентской TimeZone. Но откуда он ее в общем случае знает?
в.3) Клиентский контроллер должен сам интерпретировать полученное от сервера значение с учетом TimeZone клиентской рабочей станции: var d = new Date("2015-03-24T21:00:00"); d.millisecond += Date.timeZoneOffset();

В пункте в.3) и заключается весь геморрой, связанный с тем, что нужно везде и всюду держать в уме смещение.

Если выполнить в sciter мой пример, то проблема видна более выпукло. Три элемента прибайндены к одному и тому же полю модели, при этом видно, что date я выбираю 25.03.2015, а в output-ах рисуется 24.03.2015 21:00

CS>JSON не специфицирует никак даты — т.е. это сугубо твой бизнес. Приведи свои форматы дат к Date (UTC) при отправке и получении JSON от сервера и проблемы нет.

CS>И в общем случае сервер обязан хранить даты событий в UTC.

ИМХО это диктуется бизнес-логикой. Взять ту же дату рождения человека — важный учетный и статистический показатель, UTC в данном случае вообще не нужно, а если клиент будет сам даты приводить к UTC — то даже вредно. В самом деле, человек родился 1 января 1960, а в базу ляжет 31 декабря 1959, и человек вылетит из статистики за 1960-й год
Re: Локализация дат и в распределенных приложениях
От: Sinix  
Дата: 25.03.15 07:28
Оценка: +1
Здравствуйте, baranovda, Вы писали:

B>Должен ли такое преобразование самостоятельно выполнять контрол, работающий в Presentation Layer?

B>Или же это ответственность Buisness Layer-а (контроллера, презентера или чего там еще)?

В бизнес-приложениях должно быть 2 разных типа даты-времени:
* global time (для фиксации момента наступления какого-либо факта, хранится в UTC + опционально timezone клиента). Для дотнета это будет System.DateTimeOffset.
* local time (шаблоны, расписания, время действия для всяких акций, даты договоров до заключения). Хранится просто абстрактная дата-время, без привязки к точному времени, операции сравнения к ней неприменимы. Для дотнета — System.DateTime.

Как правило local time используется только в шаблонах, при отработке в реальные бизнес-сущности данные переводятся в global time с учётом часовой зоны клиента.
Что куда относить — ответственность биз-логики, но само разделение обязательно. Это как с invariant string / current culture string: разные контексты, разная логика обработки, лучше не смешивать.
Re[2]: Локализация дат и в распределенных приложениях
От: baranovda Российская Империя  
Дата: 25.03.15 07:34
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, baranovda, Вы писали:


S>* global time (для фиксации момента наступления какого-либо факта, хранится в UTC + опционально timezone клиента). Для дотнета это будет System.DateTimeOffset.

S>* local time (шаблоны, расписания, время действия для всяких акций, даты договоров до заключения). Хранится просто абстрактная дата-время, без привязки к точному времени, операции сравнения к ней неприменимы. Для дотнета — System.DateTime.

Спасибо, это понятно. Вопрос заключается в том, должен ли UI-контрол ввода имплиситно трансформировать введенное значение в UTC,
или же это не его ответственность и контрол должен оперировать только локальными датой-временем, а трансформацией значения из/в UTC должен заниматься посредник (для веб, например какой-нибудь JavaScript-контроллер), который при необходимости добавляет-вычитает TimeZone
Re[3]: Локализация дат и в распределенных приложениях
От: Sinix  
Дата: 25.03.15 07:40
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Спасибо, это понятно. Вопрос заключается в том, должен ли UI-контрол ввода имплиситно трансформировать введенное значение в UTC,

Определяется биз-логикой.

Если это local time, то контрол должен отдавать значение как есть. Ну, или должен быть костыль, который приводит значение к тому, что ввёл пользователь.

Если это global time, то он практически никогда не задаётся через поле ввода, т.к. используется для фиксации конкретного момента времени. Если уж припёрло — контрол должен отдавать UTC time + таймзону пользователя (т.е. дотнетовский DateTimeOffset). Или снова костыль, чтобы привести значение контрола к нужному.
Re[3]: Локализация дат и в распределенных приложениях
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.15 07:44
Оценка: +3
Здравствуйте, c-smile, Вы писали:

CS>Это я к тому что даже "просто дата" должна в общем случае храниться в системе с timezone.

1. Обычное правило — дата должна храниться в UTC. Преобразования в локальную делаются "на клиенте" — там, где есть информация о географии. Т.е. когда я ввожу в систему дату "завтра в 8 утра", она конвертируется из моей локальной зоны и на сервере существует в UTC. При показе клиенту она конвертируется в его TZ, и запросто может оказаться 6ю вечера.
2. Два исключения:
— искусственная привязка к TZ. Например, если у меня еженедельный митинг назначен на 8:00 по времени Сиэтла, то я ожидаю, что он будет а 8:00 и зимой, и летом. Т.е. "абсолютное" время начала, по UTC, будет прыгать каждый раз при переходе с PST на PDT и обратно. Это заметно тем участникам, кто живёт по локальному времени с другими правилами Daylight Savings (например, всем россиянам). Если тот же митинг привяжу к времени Новосибирска (1:00), то он будет "прыгать" для участников из Сиэтла. Привязывать его к UTC не имеет смысла, т.к. тогда он будет "прыгать" для большинства участников.
— относительные времена. Скажем, будильник можно трактовать как регулярное ежедневное событие, но оно всегда привязано к локальному часовому поясу, и перемещается вместе со мной. Т.е. если у меня стоит будильник на 8 утра, то я ожидаю и в командировке просыпаться в 8 утра, а не в 6 вечера.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Локализация дат и в распределенных приложениях
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.15 07:49
Оценка: +1
Здравствуйте, baranovda, Вы писали:
B>ИМХО это диктуется бизнес-логикой. Взять ту же дату рождения человека — важный учетный и статистический показатель, UTC в данном случае вообще не нужно, а если клиент будет сам даты приводить к UTC — то даже вредно. В самом деле, человек родился 1 января 1960, а в базу ляжет 31 декабря 1959, и человек вылетит из статистики за 1960-й год
Нет, вот в данном конкретном случае только UTC и нужно, т.к. рождение — это объективное событие, дата которого не зависит от выбранного календаря.
А вот "статистика" — это всего лишь точка зрения на объективную реальность. Грубо говоря, я могу построить гистограммы рождаемости по Григорианскому календарю, а могу — по Юлианскому.
Цифры, естественно, будут отличаться — но это потому, что отличаются мои запросы.
Если я захочу получить статистику, сравнивая, скажем, количество детей родившихся ночью с количеством родившихся днём, то мне придётся помимо дат рождения хранить ещё и географию — чтобы пересчитывать UTC в локальное астрономическое время.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Локализация дат и в распределенных приложениях
От: baranovda Российская Империя  
Дата: 25.03.15 08:16
Оценка: 39 (2) +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, baranovda, Вы писали:

S>Если это local time, то контрол должен отдавать значение как есть. Ну, или должен быть костыль, который приводит значение к тому, что ввёл пользователь

Немного покопал реализации input type=date

1) Спецификация W3С сообщает, что свойство value должно возвращать string в формате RFC 3339 (YYYY-MM-DD)

2) Открываю тестовую страничку c такой формой:

<!DOCTYPE html>
<html>
<head>
<script>
function test()
{
  var d = document.getElementById("bday").value;
  alert(d);
}
</script>
</head>
<body>

<p>
Depending on browser support:<br>
A date picker can pop-up when you enter the input field.
</p>

<form action="action_page.php">
  Birthday:
  <input type="date" name="bday" id="bday">
  <input type="submit">
  <button onclick="test()">Test</button>
</form>

<p><b>Note:</b> type="date" is not supported in Internet Explorer.</p>

</body>
</html>


Opera 12.17 и Chrome возвращают мне строку в соответствии со спекой W3C

3) Пробуем вместо input type="date" сделать input type="datetime".
<!DOCTYPE html>
<html>
<head>
<script>
function testget()
{
  var d = document.getElementById("bday").value;
  alert(d);
}
function testset()
{
  var d = document.getElementById("bday");
  d.value = "2002-05-30T09:30:10+06:00";
  return false;
}
</script>
</head>
<body>

<form action="action_page.php">
  Birthday:
  <input type="datetime" name="bday" id="bday">
  <input type="submit">
</form>

<button onclick="testget()">Get datetime</button>
<button onclick="testset()">Set datetime</button>
</body>
</html>


Chrome 41 такой контрол не поддерживает, но поддерживает datetime-local

Opera 12.17 приятно удивила: она нарисовала композитный контрол, состоящий из календаря и элемента ввода времени, и рядом подписала "UTC".
Свойство value этого контрола вернуло строку "2015-03-19T12:00Z"
При записи в этот контрол времени со смещением в Опере часовой пояс игнорируется.

4) Документация по jQuery Datepicker widget вообще ничего не знает про UTC/GMT
http://api.jqueryui.com/datepicker/

* * *
Пока делаю выводы, что в реализации броузеров контролы ввода датой-временем самодеятельности не проявляют
Отредактировано 25.03.2015 8:23 α . Предыдущая версия . Еще …
Отредактировано 25.03.2015 8:19 α . Предыдущая версия .
Re[5]: Локализация дат и в распределенных приложениях
От: c-smile Канада http://terrainformatica.com
Дата: 25.03.15 16:20
Оценка:
Здравствуйте, baranovda, Вы писали:

B>* * *

B>Пока делаю выводы, что в реализации броузеров контролы ввода датой-временем самодеятельности не проявляют

Наиди разницу в этих двух случаях:

value of W3C input date/time есть строка которая в общем случае к тому что ты передаешь на сервер в виде JSON отношения не имеет — ты должен её/их конвертирвать к представлению в BL/DB.
value of Sciter input date/time есть объект Date который в общем случае к тому что ты передаешь на сервер в виде JSON отношения не имеет — ты должен её/их конвертирвать к представлению в BL/DB.

Рззница как ты понимаешь лишь в реализации двух функций parseDate/emitDate ниже:

<html>
  <head>

    <script type="text/tiscript">
    
    var json = {
      date: "2015-03-25"
    };
    
    function parseDate(str) {
      var fields = str.scanf("%d-%d-%d");
      return Date.local(fields[0],fields[1],fields[2]);
    }
    
    function emitDate(dt) {
      return String.printf("%04d-%02d-%02d",dt.year, dt.month, dt.day);
    }
    
    self.select("#show").on("click", function(){
      var dt = parseDate(json.date);
      self.select("input[name=date]").value = dt;
    })

    self.select("#save").on("click", function(){
      var dt = self.select("input[name=date]").value;
      view.msgbox(#information, emitDate(dt));
    })

    
    </script>
  </head>
<body>

  <form>
    Date: <input|date name="date"> 
  </form>
  <button id="show">Load</button>
  <button id="save">Save</button>

</body>
</html>


Что в этих parseDate/emitDate такого военного ?
Отредактировано 27.03.2015 2:07 c-smile . Предыдущая версия .
Re[5]: Локализация дат и в распределенных приложениях
От: c-smile Канада http://terrainformatica.com
Дата: 25.03.15 16:43
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Свойство value этого контрола вернуло строку "2015-03-19T12:00Z"

B>При записи в этот контрол времени со смещением в Опере часовой пояс игнорируется.

input|date, input|time и input|calendar в Sciter имеют value of Date type по одной простой причине: устранение неоднозначности.

Вот скажем есть <input type=date> и ты ему значение устанавливаешь строкой "15.03.15".
Что должно показаться? Учитывая то что HTML не специфицирует реакцию на ошибку parsing.

В Sciter перед тем как показать ты вынужден сделать new Date("15.03.15") что вызовет throw error в коде.
Re[4]: Локализация дат и в распределенных приложениях
От: c-smile Канада http://terrainformatica.com
Дата: 25.03.15 17:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>2. Два исключения:

S>- искусственная привязка к TZ. Например, если у меня еженедельный митинг назначен на 8:00 по времени Сиэтла, то я ожидаю, что он будет а 8:00 и зимой, и летом. Т.е. "абсолютное" время начала, по UTC, будет прыгать каждый раз при переходе с PST на PDT и обратно. Это заметно тем участникам, кто живёт по локальному времени с другими правилами Daylight Savings (например, всем россиянам). Если тот же митинг привяжу к времени Новосибирска (1:00), то он будет "прыгать" для участников из Сиэтла. Привязывать его к UTC не имеет смысла, т.к. тогда он будет "прыгать" для большинства участников.

Всё так но с одним исключением: сервер время начала совещания должен отдавать в UTC иначе люди из Сиэтла и из Новосиба не встретяться никогда.

Сервер хранит дату начала совещания как пару office-location / start-offset-minutes. Но отдает всегда в UTC.
Т.е. Вася Новосибирский должен видеть митинги офиса в Сиэтле в локальной зоне Новосиба. Или Гаваев каких если туда Васю забросила суровая программерская доля в тот момент.
Re[6]: Локализация дат и в распределенных приложениях
От: baranovda Российская Империя  
Дата: 25.03.15 17:10
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Рззница как ты понимаешь лишь в реализации двух функций parseDate/emitDate ниже:

CS>Что в этих parseDate/emitDate такого военного ?

Падажьжьи.
Вот взял твой пример as is, Sciter 3.2.0.6
Загрузил страницу.
Нажал на кнопку Load.
В дэйтпикере нарисовалось у тебя что? У меня — 24.03.2015, хотя json.date = "2015-03-25".
И при нажатии на Save диалог показывает 2015-03-24

Вот картинка



PS Я прекрасно понял, что творится там внутрях: после вызова parseDate дата автоматом конвертнулась в UTC, но такое поведение обескураживает, так как распарсили одно, а в месседжбоксе видим другое.
Если б я хотел отправить на сервер дату именно в UTC, я бы хотел взять локальную дату-время, вычесть из нее смещение и отправить результат.
Отредактировано 25.03.2015 17:20 α . Предыдущая версия .
Re[7]: Локализация дат и в распределенных приложениях
От: c-smile Канада http://terrainformatica.com
Дата: 25.03.15 17:45
Оценка: :)
Здравствуйте, baranovda, Вы писали:

B>Вот картинка


А вот это уже моя бага
Re[8]: Локализация дат и в распределенных приложениях
От: baranovda Российская Империя  
Дата: 25.03.15 17:55
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>А вот это уже моя бага


Стой не убегай
А таки вот это бага, фича, багофича или что-то четвертое?
В input вводим одно, в output показывается другое?

<html>
  <style>@import "plus.css"</style>
  <head>
    <script type="text/tiscript">
        include "plus.tis";
        var Model = {
            date: null;
        }
    </script>
  </head>
<body model="Model">
Date: <input|date name="date"> 
<output name="date" type="date" /> <output name="date" type="time" />
</body>
</html>
Re[5]: Локализация дат и в распределенных приложениях
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.03.15 03:53
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Всё так но с одним исключением: сервер время начала совещания должен отдавать в UTC иначе люди из Сиэтла и из Новосиба не встретяться никогда.

Вопрос "отдачи" для меня вторичен — если клиент достаточно умён, чтобы конвертировать UTC в локальную, то ок.
А если нет — то серверу придётся хранить зону в предпочтениях пользователя — вместе с locale для языка интерфейса и представления валют, дат, и чисел.

CS>Сервер хранит дату начала совещания как пару office-location / start-offset-minutes. Но отдает всегда в UTC.

CS>Т.е. Вася Новосибирский должен видеть митинги офиса в Сиэтле в локальной зоне Новосиба. Или Гаваев каких если туда Васю забросила суровая программерская доля в тот момент.
Совершенно верно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Локализация дат и в распределенных приложениях
От: B0FEE664  
Дата: 31.03.15 15:12
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Кто прав?

Я не знаю Sciter, но...
Нужно уметь различать дату и время события. Время — оно одно для всех (если не учитывать релятивистские эффекты), а вот дата...
Дата зависит от календаря и перевести одну дату в другую не так-то просто и не всегда однозначно возможно. За примерами далеко ходить не надо. Допустим вы хотите назначить встречу в день Пасхи или в первый день рамадана. В зависимости от года этой дате будет соответствовать разный день в Григорианском календаре.
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.