Timing

Working with times & time zones is always tricky, especially if you need to build a global system that is used by users in different time zones.

ABP provides a basic infrastructure to make it easy and handle automatically wherever possible. This document covers the ABP services and systems related to time and time zones.

If you are creating a local application that runs in a single time zone region, you may not need all these systems. But even in this case, it is suggested to use the IClock service introduced in this document.

IClock

DateTime.Now returns a DateTime object with the local date & time of the server. A DateTime object doesn't store the time zone information. So, you can not know the absolute date & time stored in this object. You can only make assumptions, like assuming that it was created in UTC+05 time zone. Things especially get complicated when you save this value to a database and read it later, or send it to a client in a different time zone.

One solution to this problem is always using DateTime.UtcNow and assuming all DateTime objects as UTC time. In this way, you can convert it to the time zone of the target client when needed.

IClock provides an abstraction while getting the current time, so you can control the kind of the datetime (UTC or local) in a single point in your application.

Example: Getting the current time

using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing;

namespace AbpDemo
{
    public class MyService : ITransientDependency
    {
        private readonly IClock _clock;

        public MyService(IClock clock)
        {
            _clock = clock;
        }

        public void Foo()
        {
            //Get the current time!
            var now = _clock.Now;
        }
    }
}
C#
  • Inject the IClock service when you need to get the current time. Common base classes (like ApplicationService) already inject it and provide it as a base property - so, you can directly use it as Clock.
  • Use the Now property to get the current time.

Most of the time, IClock is the only service you need to know and use in your application.

Clock Options

AbpClockOptions is the options class that is used to set the clock kind.

Example: Use UTC Clock

Configure<AbpClockOptions>(options =>
{
    options.Kind = DateTimeKind.Utc;
});
C#

Write this inside of the ConfigureServices method of your module.

The default Kind is Unspecified, which effectively disables the Clock functionality. Either make it Utc or Local if you want to get the benefit of the Clock system.

DateTime Normalization

Another important function of the IClock is to normalize DateTime objects.

Example usage:

DateTime dateTime = ...; //Get from somewhere
var normalizedDateTime = Clock.Normalize(dateTime)
C#

Normalize method works as described below:

  • Converts the given DateTime to the UTC (by using the DateTime.ToUniversalTime() method) if the current Clock is UTC and the given DateTime is local.
  • Converts the given DateTime to the local (by using the DateTime.ToLocalTime() method) if the current Clock is local and the given DateTime is UTC.
  • Sets Kind of the given DateTime (using the DateTime.SpecifyKind(...) method) to the Kind of the current Clock if given DateTime's Kind is Unspecified.

Normalize method is used by the ABP when it gets a DateTime that is not created by IClock.Now and may not be compatible with the current Clock type. Examples;

DisableDateTimeNormalization Attribute

DisableDateTimeNormalization attribute can be used to disable the normalization operation for desired classes or properties.

DateTime Converter Between UTC and User's Time Zone

Convert given UTC to user's time zone.

DateTime ConvertToUserTime(DateTime utcDateTime) and DateTimeOffset ConvertToUserTime(DateTimeOffset dateTimeOffset) methods convert given UTC DateTime or DateTimeOffset to the user's time zone.

If SupportsMultipleTimezone is false or dateTime.Kind is not Utc or these is no timezone setting, it returns the given DateTime or DateTimeOffset without any changes.

Example:

If user's TimeZone Setting is Europe/Istanbul

// 2025-03-01T05:30:00Z
var utcTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc);

var userTime = Clock.ConvertToUserTime(utcTime);

// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours later.
userTime.Kind.ShouldBe(DateTimeKind.Unspecified);
userTime.ToString("O").ShouldBe("2025-03-01T08:30:00");
C#
// 2025-03-01T05:30:00Z
var utcTime = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc), TimeSpan.Zero);

var userTime = Clock.ConvertToUserTime(utcTime);

// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours later.
userTime.Offset.ShouldBe(TimeSpan.FromHours(3));
userTime.ToString("O").ShouldBe("2025-03-01T08:30:00.0000000+03:00");
C#

Converts given user's DateTime to UTC

DateTime ConvertToUtc(DateTime dateTime) method convert given user's DateTime to UTC.

If SupportsMultipleTimezone is false or dateTime.Kind is Utc or these is no timezone setting, it returns the given DateTime without any changes.

Example:

If user's TimeZone Setting is Europe/Istanbul

// 2025-03-01T05:30:00
var userTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified); //Same as Local

var utcTime = Clock.ConvertToUtc(userTime);

// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours earlier.
utcTime.Kind.ShouldBe(DateTimeKind.Utc);
utcTime.ToString("O").ShouldBe("2025-03-01T02:30:00.0000000Z");
C#

Other IClock Properties

In addition to the Now, IClock service has the following properties:

  • Kind: Returns a DateTimeKind for the currently used clock type (DateTimeKind.Utc, DateTimeKind.Local or DateTimeKind.Unspecified).
  • SupportsMultipleTimezone: Returns true if the currently used clock is UTC.

Time Zones

This section covers the ABP infrastructure related to managing time zones.

TimeZone Setting

ABP defines a setting, named Abp.Timing.TimeZone, that can be used to set and get the time zone for a user, tenant or globally for the application. The default value is empty, which means the application will use the server's time zone.

You can change your host/tenant global time zone in the Settings Management UI

The Account Pro Module supports user to set their own time zone in the account settings page.

See the setting documentation to learn more about the setting system.

UseAbpTimeZone Middleware

The app.UseAbpTimeZone() middleware is used to set the time zone for the current request.

*  It will get timezone from settings, the order is `User` -> `Tenant` -> `Application/Global`.
*  If current request is anonymous, it will get timezone from the request header/cookie/form/query string. the key is `__timezone`.

If you want to get current timezone, you can inject ICurrentTimezoneProvider service. Please add this middleware after authentication.

ITimezoneProvider

ITimezoneProvider is a service to simply convert Windows Time Zone Id values to Iana Time Zone Name values and vice verse. It also provides methods to get the list of these time zones and get a TimeZoneInfo with a given name.

It has been implemented using the TimeZoneConverter library.

Contributors


Last updated: April 08, 2025 Edit this page on GitHub

Was this page helpful?

Please make a selection.

To help us improve, please share your reason for the negative feedback in the field below.

Please enter a note.

Thank you for your valuable feedback!

Please note that although we cannot respond to feedback, our team will use your comments to improve the experience.

Community Talks

Real World Problems and Solutions with AI

27 Feb, 17:00
Online
Watch the Event
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book