- ABP Framework version: v4.4.3
- UI type: Angular
- DB provider: EF Core
- Tiered (MVC) or Identity Server Separated (Angular): no
I want to convert some DateTime UTC of a report entity, not to my "local" timezone but to another which the name will be saved on this same report entity.
I had a look around and it seems do not really understand on how it works.
I checked this doc https://docs.abp.io/en/abp/latest/Timing#clock-options and made some tests. At the moment we use options.Kind = DateTimeKind.Utc, so the DateTime on the database are in UTC, when I show them on my view, it is changed regarding my local DateTime which is fine. I did the test to replace Utc by local, and as expected, I got the same value from the datbase in my UI.
To try to understand more, I put a breakpoint on my code, and I did notice that either Utc or Local, the value coming from the database remain the same, the one from the database, it means the "transformation" have not been done yet. It makes sense actually, as the conversion should be done in front-end to have local timezone if I am right.
I then made a test on my UI, to show my date in 2 "different" ways, one showing the "raw" value, another formatted:
And I got this result:
So we can see that the "raw" value is kept as same as on the database, but when I "format" on date, it will convert to the local timezone.
My question here, is how {{ row.endDateTime | date: 'HH:mm' }} convert to my local time or not depending on the AbpClockOptions kind values? I can not find anything on Angular.
I am looking at ABP doc, but appart the link I shared before, I do not find much. Then from here, I will have a way to convert to the TimeZone I want or it is in some ABP angular packages?
Thanks
6 Answer(s)
-
0
I had a closer look, in my previous message I was a bit wrong:
When I select option Utc, in back-end I got a date and type of kind Utc
and the "raw" value in front-end is 2021-09-15T14:29:09.767Z
When I select option Local, in back-end I got a date and type of kind Unspecified, is it normal? It should not be local instead?
and the "raw" value in front-end is 2021-09-15T14:29:09.767**+07:00**
It then use DatePipe to convert in local or not?
https://angular.io/api/common/DatePipe
-
0
I find out on how to convert on a specific timezone for a label. I need to add the UTC I want like this (on here I get Clock Utc option, so the string is Z:
{{ '2021-09-17T03:00:08Z' | date: 'short' :'UTC +2' }}
The problem here, is that I do this on the HTML, from my angular I get this, is there any way to make change on each element of this Abp list:
Plus, if I find a way to show it with the TimeZone I want, how can I convert on the way back when it passed through the formControlName property? Does ABP has anything to convert it or I had to find out on how Angular do it?
-
0
Hello,
The best way to ensure displayed time consistency across different timezones is to return this value as a string from the backend, so the client timezone won't change how it is displayed.
Regarding your other question; internally we use the date picker component of
ng-bootstrap
which allows us to provide our ownDateTimeAdapter
. However, as far as I can see that you use another library that may have a similar option.Here is how we achieve such a thing with
NgbDatePicker
Here is DateTimeAdapter
And here is how we utilize it in a component
-
0
Thanks for your answer, but it is not exactly what I want to do. I want to show in a specific TimeZone for all users, plus of that, I should be able to edit the value, so sending to a datetime picker will not work.
In my example here, I want to show the value from Paris local zone (UTC+2), but I am based is SE Asia (UTC+7)
I am usingClock Kind as Utc, database value is: 2021-06-08 09:00:00.0000000
My back-end datetime value get the same value with Utc kind.
// 1- I define my timezone var zone = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time"); // 2- I convert my time from Utc to Paris local time tmpStartReporttime = TimeZoneInfo.ConvertTimeFromUtc(tmpStartReporttime.Value, zone); So I get the time increased from 2 hours (UTC+1 + DST = 2) which is 11:00
// 3- I change kind to local as the previous method change it to unspecified. tmpStartReporttime = DateTime.SpecifyKind(tmpStartReporttime.Value, DateTimeKind.Local); I get now still 11:00 but local instead of Unspecified
It is then sent to my Angular front-end. I sent local value, so here, it seems it convert the raw from the local value sent, using the local Timezone which is SEA (UTC -7). So now the value done through datepipeline is ok, but the "raw" is 7 hours earlier.
The issue here, is that the value returned by Angular to my back-end is UTC, so it is -7 value from my UI, it convert from my actual local timezone... For example, here I did put 11:10, but the utc is 04:10
If on the step 3 I do not change Utc to local, the value will be changed by date pipeline so added 7 hours more
About using NgbDatePicker, I did try but this component do not let the user choose date AND time on his UI
-
0
What I meant by "The best way to ensure displayed time consistency across different timezones is to return this value as a string from the backend, so the client timezone won't change how it is displayed." is to send date objects as strings across platforms and convert it in locally. If you send a timestamp, when it is converted to a local timezone, it'll differ.
For example; my timezone is GMT+3 and the timestamp of the date '19/10/2021 00:00:00' is 1634590800. If I send this to a backend with timezone GMT+1, it will be converted to '18/10/2021 23:00:00', instead, I should just send '19/10/2021 00:00:00' as a string and let the backend convert it to a date object with its own timezone. The same goes for the frontend as well. The only thing that frontend and backend needs to shake on is the datetime format, then they can convert strings to date objects on their own.
Would that work out for you?
-
0
Thanks for your answer, it was helpfull even I did a bit differently. I take the value from JavaScript on "local", means the value I selected with my DateTimePicker:
startDateTimeString = this.startDateTime.getFullYear() + String(1 + this.startDateTime.getMonth()).padStart(2,"0") + String(this.startDateTime.getDate()).padStart(2,"0") + String(this.startDateTime.getHours()).padStart(2,"0") + String(this.startDateTime.getMinutes()).padStart(2,"0");
I then send this string '202110061930' to my back-end and create a new DateTime:
var startDateTimeLocal = new DateTime(Convert.ToInt32(input.StartDateTimeString.Substring(0, 4)), Convert.ToInt32(input.StartDateTimeString.Substring(4, 2)), Convert.ToInt32(input.StartDateTimeString.Substring(6, 2)), Convert.ToInt32(input.StartDateTimeString.Substring(8, 2)), Convert.ToInt32(input.StartDateTimeString.Substring(10, 2)), 0, DateTimeKind.Unspecified);
I then convert it in Utc based on a TimeZone defined on the same entity which have this DateTime and send it to the database in Utc.
For that I used NodaTime instead of using the TimeZone of DotNet Framework.
Now all is working well :)