diff --git a/devdocs/specs/core-time-and-dates.txt b/devdocs/specs/core-time-and-dates.txt new file mode 100644 index 00000000..4b9cebb6 --- /dev/null +++ b/devdocs/specs/core-time-and-dates.txt @@ -0,0 +1,7 @@ +TIME (DATE AND TIME handling) + +RAVEN stores all times and dates in UTC in DB and internally all is UTC +User has a timezone offset setting which is used to format dates for display at the client +Dates coming from the client are all assumed to be in UTC format (i.e. converted at the client from input) +TimeZoneOffset is also used for relative date filters in list filter retrieval. + - i.e. "NextMonth" is assumed to be client relative, so the server will use their offset to calculate what next month meens to them in the query builder diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index 03b04bb0..75cf63de 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -355,11 +355,12 @@ namespace AyaNova var ct = context.RequestServices.GetService(); //get the user record - var u = ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, localeId = m.LocaleId }).First(); + var u = ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, localeId = m.LocaleId, tzOffset = m.UserOptions.TimeZoneOffset }).First(); context.Request.HttpContext.Items["AY_ROLES"] = u.roles; context.Request.HttpContext.Items["AY_USERNAME"] = u.name; context.Request.HttpContext.Items["AY_USER_ID"] = u.id; context.Request.HttpContext.Items["AY_LOCALE_ID"] = u.localeId; + context.Request.HttpContext.Items["AY_USER_TZ_OFFSET"] = u.tzOffset; diff --git a/server/AyaNova/biz/FilterSqlCriteriaBuilder.cs b/server/AyaNova/biz/FilterSqlCriteriaBuilder.cs index 6f0ea5be..5d1a751b 100644 --- a/server/AyaNova/biz/FilterSqlCriteriaBuilder.cs +++ b/server/AyaNova/biz/FilterSqlCriteriaBuilder.cs @@ -9,7 +9,7 @@ namespace AyaNova.Biz public static class FilterSqlCriteriaBuilder { //"SELECT *, xmin FROM AWIDGET name Like 'BoolDataFilterTest%' AND active = true AND " - public static string DataFilterToSQLCriteria(AyaNova.Models.DataFilter dataFilter, FilterOptions filterOptions) + public static string DataFilterToSQLCriteria(AyaNova.Models.DataFilter dataFilter, FilterOptions filterOptions, decimal timeZoneOffset) { if (string.IsNullOrWhiteSpace(dataFilter.Filter)) @@ -38,7 +38,7 @@ namespace AyaNova.Biz var dataType = filterOptions.Flds.Find(x => x.Fld == fld).Type; - sb.Append(DataFilterToColumnCriteria(fld, dataType, opType, val, tagList)); + sb.Append(DataFilterToColumnCriteria(fld, dataType, opType, val, tagList, timeZoneOffset)); if (i < FilterArray.Count - 1) { sb.Append(" AND "); @@ -51,7 +51,7 @@ namespace AyaNova.Biz /// /// Translate DataFilter to Postgres friendly SQL criteria /// - private static string DataFilterToColumnCriteria(string sColumn, string sDataType, string sOperator, string sValue, List sTags)//, bool IsCompound) + private static string DataFilterToColumnCriteria(string sColumn, string sDataType, string sOperator, string sValue, List sTags, decimal timeZoneOffset)//, bool IsCompound) { bool TagFilter = sTags.Count < 0; StringBuilder sb = new StringBuilder(); diff --git a/server/AyaNova/models/UserOptions.cs b/server/AyaNova/models/UserOptions.cs index 81963bb8..e564448f 100644 --- a/server/AyaNova/models/UserOptions.cs +++ b/server/AyaNova/models/UserOptions.cs @@ -16,6 +16,12 @@ namespace AyaNova.Models //------------- [EmailAddress] public string EmailAddress { get; set; } + /// + /// As of today Dec 10 2018 all time zones in the world are either on the hour, half hour or 45 minute mark from utc so + /// keeping this value as decimal hours for back compatibility with v7 and easier for user to enter + /// 8.5 for 8:30 time difference or 12.75 for 12:45 time differnce for example + /// + /// public decimal TimeZoneOffset { get; set; } public int UiColor { get; set; }