bpm 5.4 on-site

В базе данных хранится, например, 11 ч 41 мин, а в карточке отображается 18 ч 41, т.е. не учитывает мой часовой пояс. Как это исправить?

Нравится

18 комментариев

о да)
это вечная проблема всех версий ТС
Даже тут, на форуме, часовой пояс сообщений не учитывается
я пишу по московскому времени, а отображается на форуме киевское время ...)
простите за флуд

мы у себя в ТС 3.х решали это тем, что просто использовали везде серверное время
плюс у SQL есть удобный формат даты с UTC

но у нас еще и проблема была в том, что у террасофт 3.х не разделено, где какое время будет использоваться с часовым поясом, а где без
и в результате, если использовать часовые пояса, то у нас, например, даты рождения контактов у некоторых людей становились не, допустим, 09.01.01 (00:00), а 08.01.01 22:00 )))
мило было)

Версия 5.4, а не 3.х

Здравствуйте, Илья.

По умолчанию на клиенте время берется из браузера, который, в свою очередь, берет время из системных настроек.

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

В таблице SysAdminUnit у пользователя есть колонка TimeZoneId, куда Вы можете установить определенный часовой пояс из таблицы TimeZone, где хранятся все часовые пояса.

Например, следующим скриптом мы принудительно установим часовой пояс GMT+06:00 Новосибирск пользователю Supervisor:

update SysAdminUnit
set TimeZoneId = 
(select Id from TimeZone where Name = '(GMT+06:00) Новосибирск')
where Name = 'Supervisor'

"Соколов Илья Андреевич" написал:Версия 5.4, а не 3.х

"Калинин Иван" написал:мы у себя в ТС 3.х

я лишь привел пример и поделился опытом. я прекрасно видел, что ваша версия не 3.х

Так же отображает другой часовой пояс.

Здравствуйте, Илья.

Если проблема справедлива для раздела "Активности", прошу применить исправления ниже, предварительно выполнив резервную копию базы данных (!).

1. В схеме «ActivityUtils» найти статический метод «TryGetActivityPeriod» и заменить его содержимое, чтобы получилось так:

public static bool TryGetActivityPeriod(UserConnection userConnection, NameValueCollection queryString, HttpServerUtility server, out DateTime startDate, out DateTime dueDate) {
bool result = false;
                var currentDateTime = userConnection.CurrentUser.GetCurrentDateTime();
                startDate = currentDateTime;
                dueDate = currentDateTime;
                string startDateString = queryString[StartDateKey];                                     
                string dueDateString = queryString[DueDateKey];
                if (!string.IsNullOrEmpty(startDateString) && !string.IsNullOrEmpty(dueDateString)) {
                                result = DateTime.TryParse(server.UrlDecode(startDateString), CultureInfo.InvariantCulture, DateTimeStyles.None, out startDate) &&
                                DateTime.TryParse(server.UrlDecode(dueDateString), CultureInfo.InvariantCulture, DateTimeStyles.None, out dueDate);
                }
                return result;
}

2. Сохранить изменения (НЕ ПУБЛИКОВАТЬ)
3. В процессе схемы «CallEditPage» найти ScriptTask «ChildPageLoadCompleteAfterBaseScript» (событие «PageLoadComplete» вызов после базового). В этой схеме заменить содержимое ScriptTask на:

if (IsNew) {
                var startDate = UserConnection.CurrentUser.GetCurrentDateTime();
                var dueDate = UserConnection.CurrentUser.GetCurrentDateTime();
                var periodFromQueryString = Terrasoft.Configuration.ActivityUtils.TryGetActivityPeriod(UserConnection, Page.Request.QueryString, Page.Server, out startDate, out dueDate);
 
                var defValues = Terrasoft.Configuration.ActivityUtils.GetActivityDefValues(UserConnection);
 
                var dataSource = Page.DataSource;
                dataSource.ActiveRow.SetColumnValue("StartDate", !periodFromQueryString ? startDate : defValues.StartDate);
                dataSource.ActiveRow.SetColumnValue("DueDate", !periodFromQueryString ? dueDate : defValues.DueDate);
                dataSource.ActiveRow.SetColumnValue("OwnerId", defValues.OwnerId);
                dataSource.ActiveRow.SetColumnValue("AuthorId", defValues.AuthorId);
                Page.StartDateEdit.SetValue(!periodFromQueryString ? startDate : defValues.StartDate);
                Page.DueDateEdit.SetValue(!periodFromQueryString ? dueDate : defValues.DueDate);
                Page.OwnerEdit.SetValueAndText(defValues.OwnerId, defValues.OwnerName);
 
                if (Page.Request.QueryString[Terrasoft.Configuration.ActivityUtils.ShowInScheduleKey] == bool.TrueString) {
                               dataSource.ActiveRow.SetColumnValue("ShowInScheduler", true);
                               Page.ShowInShedulerEdit.Checked = true;
                }              
}
 
if (!(IsNew || IsCopy) && Page.DataSource.Rows[0].GetTypedColumnValue<bool>("Status_Finish")) {
                Page.ResultEdit.Enabled = true;
                Page.DetailedResultEdit.Enabled = true;
}
var allowedResult = Page.DataSource.ActiveRow.GetTypedColumnValue<string>("AllowedResult");
AllowedResults = string.IsNullOrEmpty(allowedResult) ? new Dictionary<Guid, string>() : 
                JsonConvert.DeserializeObject<Dictionary<Guid, string>>(allowedResult);
 
if (Page.DataSource.Rows.Count > 0) {
                Page.RemindToAuthorDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue<bool>("RemindToAuthor");
                Page.RemindToOwnerDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue<bool>("RemindToOwner");
}
return true;

4. Сохраняем изменения и сохраняем (НЕ ПУБЛИКУЕМ) схему процесса.
5. В процессе схемы «TaskEditPage» найти ScriptTask «ChildPageLoadCompleteAfterBaseScript» (событие «PageLoadComplete» вызов после базового). В этой схеме заменить содержимое ScriptTask на:

if (IsNew) {
                var startDate = UserConnection.CurrentUser.GetCurrentDateTime();
                var dueDate = UserConnection.CurrentUser.GetCurrentDateTime();
                var periodFromQueryString = Terrasoft.Configuration.ActivityUtils.TryGetActivityPeriod(UserConnection, Page.Request.QueryString, Page.Server, out startDate, out dueDate);
 
                var defValues = Terrasoft.Configuration.ActivityUtils.GetActivityDefValues(UserConnection);
 
                var dataSource = Page.DataSource;
                dataSource.ActiveRow.SetColumnValue("StartDate", !periodFromQueryString ? startDate : defValues.StartDate);
                dataSource.ActiveRow.SetColumnValue("DueDate", !periodFromQueryString ? dueDate : defValues.DueDate);
                dataSource.ActiveRow.SetColumnValue("OwnerId", defValues.OwnerId);
                dataSource.ActiveRow.SetColumnValue("AuthorId", defValues.AuthorId);
                Page.StartDateEdit.SetValue(!periodFromQueryString ? startDate : defValues.StartDate);
                Page.DueDateEdit.SetValue(!periodFromQueryString ? dueDate : defValues.DueDate);
                Page.OwnerEdit.SetValueAndText(defValues.OwnerId, defValues.OwnerName);
 
                if (Page.Request.QueryString[Terrasoft.Configuration.ActivityUtils.ShowInScheduleKey] == bool.TrueString) {
                               dataSource.ActiveRow.SetColumnValue("ShowInScheduler", true);
                               Page.ShowInSchedulerEdit.Checked = true;
                }
}
 
if (!(IsNew || IsCopy) && Page.DataSource.Rows[0].GetTypedColumnValue<bool>("Status_Finish")) {
                Page.ResultEdit.Enabled = true;
                Page.DetailedResultEdit.Enabled = true;
}
var allowedResult = Page.DataSource.ActiveRow.GetTypedColumnValue<string>("AllowedResult");
AllowedResults = string.IsNullOrEmpty(allowedResult) ? new Dictionary<Guid, string>() : 
                JsonConvert.DeserializeObject<Dictionary<Guid, string>>(allowedResult);
Page.CategoryEdit.Enabled = (AllowedResults as Dictionary<Guid, string>).Count == 0;
if (Page.DataSource.Rows.Count > 0) {
                Page.RemindToAuthorDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue<bool>("RemindToAuthor");
                Page.RemaindToOwnerDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue<bool>("RemindToOwner");
}
return true;

6. Сохраняем изменения и сохраняем (НЕ ПУБЛИКУЕМ) схему процесса.
7. В процессе схемы «EmailEditPage» найти ScriptTask «EnableSendButton»/« Set Default Values, Activate Mail Send Button» (событие «PageLoadComplete» вызов после базового). В этой схеме заменить содержимое ScriptTask на:

if (IsNew) {
                var startDate = UserConnection.CurrentUser.GetCurrentDateTime();
                var dueDate = UserConnection.CurrentUser.GetCurrentDateTime();
                var periodFromQueryString = Terrasoft.Configuration.ActivityUtils.TryGetActivityPeriod(UserConnection, Page.Request.QueryString, Page.Server, out startDate, out dueDate);
 
                var defValues = Terrasoft.Configuration.ActivityUtils.GetActivityDefValues(UserConnection);
 
                var dataSource = Page.DataSource;
                dataSource.ActiveRow.SetColumnValue("StartDate", !periodFromQueryString ? startDate : defValues.StartDate);
                dataSource.ActiveRow.SetColumnValue("DueDate", !periodFromQueryString ? dueDate : defValues.DueDate);
                dataSource.ActiveRow.SetColumnValue("OwnerId", defValues.OwnerId);
                dataSource.ActiveRow.SetColumnValue("AuthorId", defValues.AuthorId);
 
                Page.StartDateEdit.SetValue(!periodFromQueryString ? startDate : defValues.StartDate);
                Page.DueDateEdit.SetValue(!periodFromQueryString ? dueDate : defValues.DueDate);
                Page.OwnerEdit.SetValueAndText(defValues.OwnerId, defValues.OwnerName);
 
                if (Page.Request.QueryString[Terrasoft.Configuration.ActivityUtils.ShowInScheduleKey] == bool.TrueString) {
                               dataSource.ActiveRow.SetColumnValue("ShowInScheduler", true);
                               Page.ShowInSchedulerEdit.Checked = true;
                }
 
                var parameterContactId = GetIdFromParameter("ContactId");
                if (!parameterContactId.Equals(Guid.Empty)) {
                               dataSource.ActiveRow.SetColumnValue("Recepient", GetRecipientByContact(parameterContactId));
                }
 
                var parameterTemplateId = GetIdFromParameter("TemplateId");
                if (!parameterTemplateId.Equals(Guid.Empty)) {
                /*
                               Activity activity = GetActivity();
                               var condition = new Dictionary<string, object>() {
                                                                                                                             { "Activity", activity.Id },
                                                                                                                             { "EmailTemplate", parameterTemplateId }
                                                                                                              };
 
                               var link = new EmailTemplateActivity(UserConnection);
 
                               bool isFetched = false;
                               try {
                                               isFetched = link.FetchFromDB(condition);
                               } catch { continue; }
 
                               if (!isFetched) {
                                               link.SetDefColumnValues();
 
                                               link.ActivityId = activity.Id;
                                               link.EmailTemplateId = parameterTemplateId;
 
                                               link.Save();
                               }
                               */
                               AddTemplateToEmailBody(parameterTemplateId, true);                                                           
                }
}
 
if (!IsNew && !IsCopy) {
                var emailStatusId = Page.DataSource.Rows[0].GetTypedColumnValue<Guid>("EmailSendStatusId");
                var emailStatus_Sended = new Guid("8074FFC0-6107-E011-A646-16D83CAB0980");
                var emailStatus_InProgress = new Guid("603BA6AF-6107-E011-A646-16D83CAB0980"); 
                if(emailStatusId.Equals(emailStatus_Sended) || emailStatusId.Equals(emailStatus_InProgress)) {
                               Page.EmailButton.Enabled = false;
                }
 
                if(emailStatusId.Equals(emailStatus_Sended)) {
                               Page.SenderEdit.Enabled = false;
                               Page.RecepientEdit.Enabled = false;
                               Page.CopyRecepientEdit.Enabled = false;
                               Page.BlindCopyRecepientEdit.Enabled = false;
                               Page.TitleEdit.Enabled = false;
                               Page.OwnerEdit.Enabled = false;
                               Page.StatusEdit.Enabled = false;
                               Page.BodyEdit.Enabled = false;
                }
}
 
Page.AddTemplateButton.Enabled = !IsNew && !IsCopy;
Page.CreateMessageFromTemplatesButton.Enabled = !IsNew && !IsCopy;
if (Page.DataSource.Rows.Count > 0) {
                Page.RemindToAuthorDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue<bool>("RemindToAuthor");
                Page.RemindToOwnerDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue<bool>("RemindToOwner");
}
return true;

8. Сохраняем изменения, и ПУБЛИКУЕМ схему. (Подтянется публикация измененных схем при компилировании конфигурации).
9. Проверяем.
Все.

Нет, это не раздел активности. Я создал свой раздел.

Нет, это не раздел активности. Я создал свой раздел.

Нет, это не раздел активности. Я создал свой раздел.

Илья, проблемы со временем только в Вашем разделе или во всех разделах системы?

Только в моём разделе.

Илья,

проблема в том, что в базе данные хранятся в UTC формате, а затем у каждого пользователя отображаются в соответствии с часовым поясом его браузера.

В Ваш раздел данные попадают напрямую SQL-запросом и уже в базу они сохраняются со смещением согласно Вашему часовому поясу.

Решением является писать записи в Ваш раздел в формате UTC. Для этого существуют функция SQL:

GETUTCDATE()

http://msdn.microsoft.com/en-us/library/ms178635.aspx

Працюю з версією 5.4

Намагаюсь розібратися з часовим поясом.
Формую в SQL вибірку для формування звіту.
В базі дати зберігаються як UTC.
Витягую значення

var offSet=UserConnection.CurrentUser.TimeZone.BaseUtcOffset.TotalMinutes

яке в SQL-запиті підставляю в дати:

DATEADD(MINUTES,offSet,<дата>)

Все добре, окрім одного:
UserConnection.CurrentUser.TimeZone.DisplayName =>
displayName : (UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
але по карточці звернення бачу, що зміщення не +2:00, а +3:00

Поки що не знайшов, як вийти на +3:00

Видимо, ещё один час даёт летнее время.

"Зверев Александр" написал:

Видимо, ещё один час даёт летнее время.


Може й так, але яким чином та година враховується ?
В одному скрипті я отримую значення:

var respondedOn = activeRow.GetTypedColumnValue<DateTime>("RespondedOn");

та

var	offSet = UserConnection.CurrentUser.TimeZone.BaseUtcOffset.TotalMinutes;

respondedOn враховує +3:00
а
offSet = 120

Тут пишут, что для часового пояса можно получить, переводят ли часы:


Use TimeZoneInfo.IsDaylightSavingTime Method (DateTimeOffset) to find if it is currently Daylight saving for your Timezone.

var info = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
bool isDaylightSaving = info.IsDaylightSavingTime(localServerTime);

There are further examples here

А тут упоминают такое свойтво:

DateTimeOffset.Now.Offset.TotalMinutes

Оно даёт 2 или 3?

offSet : 180

Те, що треба. Дякую

Показать все комментарии