Open Closed

DateTime properties are not converted from UTC to Local timezone (UTC+3) #10158


User avatar
0
omer_yel created

Hi, we have a problem with datetime timezone conversion. We have set datetimekind as UTC to save datetime values in UTC format.

For demonstration purposes, we set our local time zone for currently logged in user.

Id specified in image send request for list. In retrieved list creationTime is in UTC format. We manually set localtime for creationTime, then it became local time. But output of request was unmodified. Its creation time in UTC format. As you see userIds are same.

  • Why does not setting user specific timezone work? Why does not it automatically convert UTC to local datetime properties?
  • Why does our manually changed creationTime reset itself to UTC format after existing appservice method?

What can we do to solve this problem?


2 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    1. Solution
    • What ABP does (and does not) do

      • When you set AbpClockOptions.Kind = DateTimeKind.Utc, ABP normalizes DateTime values to UTC for persistence and for API responses. This is by design. ABP does not automatically convert DateTime values to the user’s local time in JSON responses. Clients should receive UTC (e.g., 2025-11-25T12:19:28Z) and render/convert to the user time zone on the UI.
      • ABP performs timezone conversions only when you explicitly call the helpers:
        • Server-side: IClock.ConvertToUserTime(...) and IClock.ConvertToUtc(...)
        • JavaScript: abp.clock.normalizeToLocaleString(...) and abp.clock.normalizeToString(...)
        • Blazor: inject IClock and call ConvertToUserTime/ConvertToUtc where you display or accept input.
    • Why your user-specific TimeZone setting did not change the API output

      • The user TimeZone setting (Abp.Timing.TimeZone) affects conversions performed by IClock.*Convert… methods and the ABP UI helpers, not the raw data returned by your API. With UTC clock, API responses stay UTC. You should convert on the UI or on the view model that is specifically meant for display.
    • Why your manual CreationTime change “reverted” after leaving the AppService

      • You are mapping entities to DTOs and returning them. If you mutate a DateTime to local with ToLocalTime(), you produce a local DateTime (Kind=Local/Unspecified). Before serialization, ABP’s JSON serialization keeps it as a DateTime; since the global clock is UTC, and you haven’t used IClock to convert for output, the serializer writes ISO-8601 UTC ending with Z for DateTime by convention. Net result: your manual local conversion is lost in the returned JSON. This is expected; don’t try to store UI-local values into your DTO model. Keep DTOs in UTC and convert for display.
    • Recommended, working setup for your stack (Blazor Server, ABP 9.0.2)

      1. Keep everything in UTC
    Configure<AbpClockOptions>(options =>
         {
             options.Kind = DateTimeKind.Utc;
         });
    
    1. Set the user’s timezone via setting Abp.Timing.TimeZone (e.g., "Turkey Standard Time" or the IANA name depending on your environment).
    2. Blazor Server UI: convert explicitly when showing values and convert back to UTC when saving.
      • Display:
    @inject IClock Clock
           @Clock.ConvertToUserTime(dto.CreationTime).ToString("yyyy-MM-dd HH:mm:ss")
    
     - Input -> Save:
       - If the user picked a DateTime in their local time:
    
    dto.ScheduledTime = Clock.ConvertToUtc(userInputLocalDateTime);
    
       - If you use DateTimeOffset pickers, prefer storing DateTimeOffset in the entity/DTO where appropriate, or convert via Clock.ConvertToUtc(offset.DateTime) when persisting as DateTime.
    
    1. If you have MVC/Razor Pages or JS:
      • Add UseAbpTimeZone middleware on the server app to let ABP detect the browser timezone when a per-user/tenant setting is not present.
      • For JS forms using ABP TagHelpers/DatePicker, call before submit:
    $form.handleDatepicker('input[type="hidden"][data-hidden-datepicker]');
    
       This uses abp.clock.normalizeToString under the hood to send UTC values.
     - For displaying in JS (DataTables or custom UI):
    
    abp.clock.normalizeToLocaleString(utcIsoString)
    
    1. Don’t call DateTime.ToLocalTime() on DTOs you return from services. Instead:
      • Return UTC to clients.
      • Or, if you really must return localized values for a specific endpoint, use IClock.ConvertToUserTime on a dedicated “view”/presentation DTO and mark the property as string (already formatted) or DateTimeOffset with proper offset. Avoid mixing with standard CRUD DTOs which should remain UTC.
    • Quick example (Blazor Server list page)
    @inject IClock Clock
    
      // In the grid template:
      @Clock.ConvertToUserTime(item.CreationTime).ToString("yyyy-MM-dd HH:mm:ss")
    
      // When creating/updating from local picker value:
      entity.ScheduledOnUtc = Clock.ConvertToUtc(LocalPickerValue);
    
    • Checklist to solve your issue now
      • Keep AbpClockOptions.Kind = Utc across all apps/services.
      • Ensure the user’s Abp.Timing.TimeZone setting is set (e.g., “Turkey Standard Time”) for that user.
      • In Blazor components, show DateTimes via Clock.ConvertToUserTime; do not expect API to return local times.
      • On create/update, convert UI-picked local times back to UTC with Clock.ConvertToUtc before saving.
      • If you use JS pages, add UseAbpTimeZone middleware and call $form.handleDatepicker(...) on submit.
    1. Sources
    • https://docs.abp.io/en/abp/latest/Framework/Infrastructure/Timing
    • https://abp.io/docs/latest/framework/infrastructure/timing
    • Community article: Developing a Multi-Timezone Application Using the ABP Framework (explains IClock, UseAbpTimeZone, Blazor/JS usage) https://abp.io/community/articles/zk7fnrdq

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Here is an article about multiple time zones. Can you check it first?

    https://abp.io/community/posts/developing-a-multitimezone-application-using-the-abp-framework-zk7fnrdq

    Thanks.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on December 03, 2025, 13:19
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.