Setting universal time and offset

Internally, the kernel uses UTC (Coordinated Universal Time) and stores an offset for the difference between UTC and local time which is made up of both the time zone and any daylight saving time added. This removes the responsibility for handling time zones and daylight saving from the kernel to a user side "timezone" server. A positive offset indicates a time ahead of UTC: a negative offset indicates a time behind UTC.

The API below is used to set and get the UTC offset values.


Setting the UTC time and offset requires the WriteDeviceData security capability.

Customizing the default time zone setting

The local time zone is calculated using an offset from UTC. User::SetUTCOffset() is used to set the offset to the required value. This function is called by three different components at boot up:

  • EStart - sets the offset at the start of the boot process and then provides the correct time for parts of the system that are initialized before the TimeZone and Locale services are running.

  • InitialiseLocale - sets and gets the locale information stored within the repository. This is necessary if the TimeZoneServer is not included.

  • TimeZoneServer - is an optional service that device manufactures can choose to include. It is recommended that the offset is set both here and within InitialiseLocale.


The call in EStart is required for backwards compatibility with systems that do not use the TimeZoneServer. The call in EStart also allows many parts of the system to see the correct time before the timezone/locale services are up and running. If the timezone offset is not set during startup then many components may, for that period, see the wrong time.

The data format for the persisted locale data makes no allowance for daylight savings that are not equal to one hour, but in new code the daylight savings flag is never used (specifically because of this issue) and the offset is adjusted by the correct amount instead.

To alter the default time zone operation within EStart , provide your own implementation of the EStart virtual function TFSStartup::LoadLocale() . See EStart: customizing code .

The offset set through EStart is retrieved through User::UTCOffset() .


InitialiseLocale initializes and persists changes to the system locale settings. The system locale data is persisted using the central repository. The executable initialiseLocale.exe loads the system locale data at device boot and ensures that changes to the system locale data are persisted.

Once initialiseLocale.exe has been loaded (as part of the system boot sequence) the contents of the system locale data are initialized and any subsequent changes to the system locale settings are persisted without any intervention from the application or component making the changes.

Changing System Locale Settings

Create an empty TExtendedLocale object and use LoadSystemSettings() to get the settings from the repository, make changes and save them with SaveSystemSettings() . This function generates a notification for system locale changes so changes to the locale information may not be immediate.

For example, an application that wishes to change the system time and date settings (without changing any other locale settings) goes through the following steps:

  1. Create an empty instance of TExtendedLocale .

             TExtendedLocale myExtendedLocale;
  2. Initialize it to the current system settings.

  3. Change the time and date settings locally.

             myExtendedLocale.LoadLocaleAspect( ELocaleTimeDateSettings, KLocaleDllTimeDateSettings );
  4. Write the new settings to the system locale data.


The security capability WriteDeviceData is required to save settings.


The time zone server simplifies the synchronisation between handsets in different time zones. For example, if one handset is in the UK and another in the US a meeting can be scheduled at the same time (UTC) and the local time is calculated for each by the time zone server.

The Time Zone Server converts UTC to local time based on different time zones and DST rules, and publishes any change to subscribing clients, for example the Calendar application. See Publish and Subscribe .

The time zone server is an optional service that licensees can choose to include otherwise another method can be used to supply the UTC offset, for example, Network time update, see RMobilePhone::GetNITZInfo() . Because the time zone server may not be included in the product it is necessary to persist the UTC offset as part of the locale data ( TLocale ). The time zone server persists the current time zone and updates the UTC offset based on whether daylight savings applies or not.

The following code example should help to illustrate the interactions that may occur if User:SetUTCOffset() or User::SetUTCTimeAndOffset() are called while the time zone server is running.

Preconditions for this code are:

  • The time zone server is not already running.

  • It is assumed that the current UTC offset is not 36000 seconds (10 hours). For describing this example, we will take the UTC to be 18000 seconds (5 hours).

       void MainL()
    RTz tz;
    TTimeIntervalSeconds offsetWhenTzRunningInitial;
    TTimeIntervalSeconds offsetWhenTzRunningAfterSetting;
    TTimeIntervalSeconds offsetWhenTzNotRunningInitial;
    TTimeIntervalSeconds offsetWhenTzNotRunningAfterSetting;

    TInt err = tz.Connect();
    User::LeaveIfError( err );
    offsetWhenTzRunningInitial = User::UTCOffset(); 
    User::SetUTCOffset( 36000 );
    User::After( 1*1000*1000 );
    offsetWhenTzRunningAfterSetting = User::UTCOffset(); 

    offsetWhenTzNotRunningInitial = User::UTCOffset(); 
    User::SetUTCOffset( 36000 );
    offsetWhenTzNotRunningAfterSetting = User::UTCOffset(); 

Given the preconditions listed, the values for the offsets retrieved are:

  1. offsetWhenTzRunningInitial 18000 (seconds).

  2. offsetWhenTzRunningAfterSetting 18000 (seconds).

  3. offsetWhenTzNotRunningInitial 18000 (seconds).

  4. offsetWhenTzNotRunningAfterSetting 36000 (seconds).

The value of offsetWhenTzRunningAfterSetting is not 36000 as one might expect from just looking at the code. This is because the time zone server observes the kernel setting of the UTC offset and when this value is changed, it checks the current time zone and ensures that the offset matches this value. The delay is placed in this example code to ensure that the time zone server is given a chance to run and to change the value.

If a call to User::UTCOffset() were made before the call to User::After() , then the value can be either 36000 or 18000 depending on the CPU load, presence of other processes and their relative priorities.