bpm 5.4 on-site
В базе данных хранится, например, 11 ч 41 мин, а в карточке отображается 18 ч 41, т.е. не учитывает мой часовой пояс. Как это исправить?
Нравится
о да)
это вечная проблема всех версий ТС
Даже тут, на форуме, часовой пояс сообщений не учитывается
я пишу по московскому времени, а отображается на форуме киевское время ...)
простите за флуд
мы у себя в ТС 3.х решали это тем, что просто использовали везде серверное время
плюс у SQL есть удобный формат даты с UTC
но у нас еще и проблема была в том, что у террасофт 3.х не разделено, где какое время будет использоваться с часовым поясом, а где без
и в результате, если использовать часовые пояса, то у нас, например, даты рождения контактов у некоторых людей становились не, допустим, 09.01.01 (00:00), а 08.01.01 22:00 )))
мило было)
Здравствуйте, Илья.
По умолчанию на клиенте время берется из браузера, который, в свою очередь, берет время из системных настроек.
В любом случае, Вы всегда можете установить конкретному пользователю определенный часовой пояс, тогда время для данного пользователя будет всегда устанавливаться согласно определенному часовому поясу:
В таблице SysAdminUnit у пользователя есть колонка TimeZoneId, куда Вы можете установить определенный часовой пояс из таблицы TimeZone, где хранятся все часовые пояса.
Например, следующим скриптом мы принудительно установим часовой пояс GMT+06:00 Новосибирск пользователю Supervisor:
[sql]
update SysAdminUnit
set TimeZoneId =
(select Id from TimeZone where Name = '(GMT+06:00) Новосибирск')
where Name = 'Supervisor'
[/sql]
"Соколов Илья Андреевич" написал:Версия 5.4, а не 3.х
"Калинин Иван" написал:мы у себя в ТС 3.х
я лишь привел пример и поделился опытом. я прекрасно видел, что ваша версия не 3.х
Здравствуйте, Илья.
Если проблема справедлива для раздела "Активности", прошу применить исправления ниже, предварительно выполнив резервную копию базы данных (!).
1. В схеме «ActivityUtils» найти статический метод «TryGetActivityPeriod» и заменить его содержимое, чтобы получилось так:
[csharp]
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;
}
[/csharp]
2. Сохранить изменения (НЕ ПУБЛИКОВАТЬ)
3. В процессе схемы «CallEditPage» найти ScriptTask «ChildPageLoadCompleteAfterBaseScript» (событие «PageLoadComplete» вызов после базового). В этой схеме заменить содержимое ScriptTask на:
[csharp]
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("Status_Finish")) {
Page.ResultEdit.Enabled = true;
Page.DetailedResultEdit.Enabled = true;
}
var allowedResult = Page.DataSource.ActiveRow.GetTypedColumnValue("AllowedResult");
AllowedResults = string.IsNullOrEmpty(allowedResult) ? new Dictionary() :
JsonConvert.DeserializeObject>(allowedResult);
if (Page.DataSource.Rows.Count > 0) {
Page.RemindToAuthorDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue("RemindToAuthor");
Page.RemindToOwnerDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue("RemindToOwner");
}
return true;
[/csharp]
4. Сохраняем изменения и сохраняем (НЕ ПУБЛИКУЕМ) схему процесса.
5. В процессе схемы «TaskEditPage» найти ScriptTask «ChildPageLoadCompleteAfterBaseScript» (событие «PageLoadComplete» вызов после базового). В этой схеме заменить содержимое ScriptTask на:
[csharp]
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("Status_Finish")) {
Page.ResultEdit.Enabled = true;
Page.DetailedResultEdit.Enabled = true;
}
var allowedResult = Page.DataSource.ActiveRow.GetTypedColumnValue("AllowedResult");
AllowedResults = string.IsNullOrEmpty(allowedResult) ? new Dictionary() :
JsonConvert.DeserializeObject>(allowedResult);
Page.CategoryEdit.Enabled = (AllowedResults as Dictionary).Count == 0;
if (Page.DataSource.Rows.Count > 0) {
Page.RemindToAuthorDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue("RemindToAuthor");
Page.RemaindToOwnerDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue("RemindToOwner");
}
return true;
[/csharp]
6. Сохраняем изменения и сохраняем (НЕ ПУБЛИКУЕМ) схему процесса.
7. В процессе схемы «EmailEditPage» найти ScriptTask «EnableSendButton»/« Set Default Values, Activate Mail Send Button» (событие «PageLoadComplete» вызов после базового). В этой схеме заменить содержимое ScriptTask на:
[csharp]
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() {
{ "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("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("RemindToAuthor");
Page.RemindToOwnerDateEdit.Enabled = Page.DataSource.Rows[0].GetTypedColumnValue("RemindToOwner");
}
return true;
[/csharp]
8. Сохраняем изменения, и ПУБЛИКУЕМ схему. (Подтянется публикация измененных схем при компилировании конфигурации).
9. Проверяем.
Все.
Нет, это не раздел активности. Я создал свой раздел.
Нет, это не раздел активности. Я создал свой раздел.
Нет, это не раздел активности. Я создал свой раздел.
Илья, проблемы со временем только в Вашем разделе или во всех разделах системы?
Илья,
проблема в том, что в базе данные хранятся в UTC формате, а затем у каждого пользователя отображаются в соответствии с часовым поясом его браузера.
В Ваш раздел данные попадают напрямую SQL-запросом и уже в базу они сохраняются со смещением согласно Вашему часовому поясу.
Решением является писать записи в Ваш раздел в формате UTC. Для этого существуют функция SQL:
[sql]
GETUTCDATE()
[/sql]
Працюю з версією 5.4
Намагаюсь розібратися з часовим поясом.
Формую в SQL вибірку для формування звіту.
В базі дати зберігаються як UTC.
Витягую значення
[csharp]
var offSet=UserConnection.CurrentUser.TimeZone.BaseUtcOffset.TotalMinutes
[/csharp]
яке в SQL-запиті підставляю в дати:
[sql]
DATEADD(MINUTES,offSet,<дата>)
[/sql]
Все добре, окрім одного:
UserConnection.CurrentUser.TimeZone.DisplayName =>
displayName : (UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
але по карточці звернення бачу, що зміщення не +2:00, а +3:00
Поки що не знайшов, як вийти на +3:00
"Зверев Александр" написал:Видимо, ещё один час даёт летнее время.
Може й так, але яким чином та година враховується ?
В одному скрипті я отримую значення:
[csharp]
var respondedOn = activeRow.GetTypedColumnValue("RespondedOn");
[/csharp]та
[csharp]
var offSet = UserConnection.CurrentUser.TimeZone.BaseUtcOffset.TotalMinutes;
[/csharp]
respondedOn враховує +3:00
а
offSet = 120
Тут пишут, что для часового пояса можно получить, переводят ли часы:
Use TimeZoneInfo.IsDaylightSavingTime Method (DateTimeOffset) to find if it is currently Daylight saving for your Timezone.[csharp]
var info = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
bool isDaylightSaving = info.IsDaylightSavingTime(localServerTime);
[/csharp]There are further examples here
А тут упоминают такое свойтво:
[csharp]
DateTimeOffset.Now.Offset.TotalMinutes
[/csharp]
Оно даёт 2 или 3?