Windows XP and Hijri Calendar Support
has a lot of interesting international features that support the Hijri calendar.
Through its national language support (NLS), Windows supports many types of
calendars, date, number and currency formats. We will start by introducing the NLS
in Windows, and how you can query the user and system locales through its
several APIs: the NLS APIs. But to understand the many features of NLS, it is
important to understand first the meaning of locale, and the difference between
the system, user and thread locales.
consists of a set of system tables that applications can access through the NLS
APIs. These system tables contain the following information:
Locale information: Such as date, time, number, or
currency format or localized names of countries, languages, or days of the
month and week.
Character mapping tables: That map local character encodings
(ANSI or OEM) to Unicode or vice versa.
contain information about keyboard layout, character entry, sorting and
On Windows XP, users can install National Language Support
for any locale via the control panel.
is a collection of language-related, user-preference information represented as
a list of values. Each system has at least one installed locale and often has
many locales from which the user may choose.
system locale determines which code page (ANSI, DOS, Macintosh) is used
on the system by default. The system locale setting affects only ANSI
applications, that is, applications that are not fully Unicode-compliant. This
is because setting the system locale to a certain language instructs Windows to
emulate a non-Unicode-based operating system (for example, Windows 95/98/Me)
localized to this language. Changing the system locale installs the necessary
bitmap font files to support non-Unicode applications in the specified
language. To select a system locale, the appropriate language group must be installed;
that is, you need the script support to select a system locale. The system
locale is a per-system setting and requires a restart to be implemented.
user locale is a per user variable that determines default sort order
and the default settings for formatting dates, times, currency, and numbers.
Although it is presented as a language (some in combination with a
country/region), it is not a language setting. For example, setting the
user locale to French means that the user wants to use the formatting
conventions of French, not necessarily the French language.
addition, the user locale determines the string that is used for the names of
the days and months. For example, if a user displays 'September 15, 2003,' the 'September' string could
change based on the user locale to “Septembre”. Changing the user locale
automatically adds an input locale with the default settings for the language.
The thread locale is a per
thread data that determines the formatting of dates, times, currency, and large
numbers for the thread. It can be used to retrieve language specific resource
from a multilingual resource file. It defaults to the value for the currently
selected user locale. To retrieve and set the thread locale, call GetThreadLocale
be able to use the Hijri Calendar as the default calendar type, there are two methods:
1- Changing the System
From the Control Panel, "Regional and Language
Options" go to the "Advanced" tab and change the "Language
for non Unicode programs" to an Arabic language.
PS. This will not affect the user interface language
It is a per-system setting that applies to all users on
the same system. This setting will require a reboot to take effect.
the User Locale
the Control Panel, “Regional and Language Options”, from “Standards and
Formats”, choose any Arabic language, then if you click “Customize”, and choose
“Date”, you can customize the format with which you want to display dates, as
well as the calendar type, in this case you can choose the Hijri calendar for thecalendar
It is a per-user setting;
therefore it applies only to the current user of the system. For example, if
your system locale is English(US), you can still display the dates in Spanish
or French formats.
You could query and modify some attributes
in the locale using the following APIs:
The GetDateFormat function
formats a date as a date string for a specified locale. This function formats
either a specified date or the local system date.
int GetDateFormat(LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpDate,
LPCTSTR lpFormat, LPTSTR lpDateStr,int cchDate);
The following code
sample displays the system date using the default system locale, and the format
const MAX_STR = 30;
MMM yyyy", strDate,MAX_STR);
And the output is:
If you try the same sample, and replace the LOCALE_SYSTEM_DEFAULT with
LOCALE_USER_DEFAULT, you would get the same result (Provided that you have
previously set both the user and system locales to Arabic-sa from the control
panel’s regional settings).
you got the Gregorian date with Arabic names, then you probably forgot to set
the calendar type to the Hijri calendar.
Using the parameter lpFormat of the GetDateFormat,
you can represent the date in any format the current locale supports; this
would override the date format setting in the control panel. For example, by
setting the format to 0, the default will be the locale’s short date format:
And the output would be:
You can also retrieve the standard date formats supported by
a given locale, by using the EnumDateFormats API.
The EnumDateFormats function
enumerates the long or short date formats that are available for a specified
locale. The value of the dwFlags parameter determines whether the long
or short date formats are enumerated. The function enumerates the date formats
by passing date format string pointers, one at a time, to the specified
application-defined callback function. This continues until the last date
format is found or the callback function returns FALSE.
lpDateFmtEnumProc, LCID Locale, DWORD dwFlags);
code sample would display all the available standard date formats for the Hijri
calendar (which is the current system calendar):
const MAX_STR =
// The callback
CALLBACK EnumDateFormatsProc(LPTSTR lpDateFormatString)
const MAX_STR =
int APIENTRY WinMain(HINSTANCE
Initialize the character array that will hold the Date Formats to Null.
the native calendar names for all available calendar
that correspond to the current user locale.
NULL,dateFormats, TEXT("Hijri Date Formats"), MB_OK|MB_RTLREADING|MB_RIGHT);
And the output is:
function enumerates calendar information for a specified locale. The CalType
parameter specifies the type of calendar information to enumerate. The function
returns the specified calendar information for all applicable calendars for the
locale or, for a single requested calendar, depending on the value of the Calendar
BOOL EnumCalendarInfo( CALINFO_ENUMPROC pCalInfoEnumProc, LCID Locale
, CALID Calendar, CALTYPE CalType);
You could display all the calendar types available for a certain
locale, using the following code sample:
const MAX_STR = 300;
BOOL CALLBACK EnumCalendarInfoProc(LPTSTR
int APIENTRY _tWinMain(HINSTANCE
the character array that will hold the calendar names to Null.
memset(calendars, 0, sizeof(calendars));
Enumerate the native calendar names for all available calendar
types that correspond to the current user locale.
// enumeration callback
LOCALE_USER_DEFAULT, // locale - any valid LCID
ENUM_ALL_CALENDARS, // does enumeration for all supported
CAL_SCALNAME); // calendar info (return the calendar name)
TEXT("Calendars names"), MB_OK|MB_RTLREADING|MB_RIGHT);
get the following output that lists all available calendars for the current
user locale (Arabic-SA):
GetCalendarInfo function retrieves information about a calendar. This
function is very similar to the EnumCalendarInfo described above.
Locale, CALID Calendar, CALTYPE CalType,
LPTSTR lpCalData, int cchData,LPDWORD lpValue);
You can specify the kind of information you want to be
retrieved from the Calendar, by setting the CalType to any of the Calendar Type
the following code sample, you could retrieve the name of the first month of
the Hijri year, by specifying CAL_SMONTHNAME1
field in the Calendar type Info
TEXT("Calendar Info"), MB_OK|MB_RTLREADING|MB_RIGHT);
And the output is:
Now, what if you are developing an application, in which you
will be utilizing the Hijri calendar and at the same time, you do not wish to
change the user settings, or require the users of your application to have to
change their user settings for this application to run correctly. This is where
the SetThreadLocale() function comes in handy.
SetThreadLocale function sets the calling thread's current locale.
BOOL SetThreadLocale (LCID Locale);
The Locale parameter can be the LOCALE_SYSTEM_DEFAULT or the LOCALE_USER_DEFAULT,
however this parameter can be a locale identifier created by the MAKELCID
macro. This macro can be useful in the previously mentioned case where you
would like to create your own locale.
The MAKELCID macro
creates a locale identifier from a language identifier.
DWORD MAKELCID (WORD wLanguageID,WORD wSortID);
The following code creates a locale identifier for the Arabic
Language identifier with a Sub language of Saudi Arabia
(as mentioned earlier, this is not a language setting, it just means you are going to use
the formatting conventions of the Arabic Language). Then you set the current thread locale to this new
locale. In this case you can have your user locale set to English (United States), in the Regional Options), and at
the same time display calendars supported by the Arabic (Saudi Arabia) locale.
MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT );
TEXT("Calendar Info"), MB_OK|MB_RTLREADING|MB_RIGHT);
And you can get the same output, you got when you had your
user locale set to Arabic (Saudi
The start of a
Hijri month is marked by the sight of the lunar crescent by a human observer. The
sight of the crescent is regulated by many factors, including the location of
sighting. Therefore it is very difficult to predict in advance the beginnings
and endings of the Hijri months. An adjustment of between zero and two days can be made to
the calendar through the registry entry AddHijriDate.
valid adjustment value.
This entry does not exist
in the registry by default. You can add it using two methods:
From Control Panel:
From Control Panel, click on “Regional
and Language Options”. In the “Standards and Formats” box, select a locale that
uses the Hijri calendar. Click on the “Customize”, and then go to the “Date”
tab. In the “Adjust Hijri date to:” drop-down list, select the
appropriate value (one or two days before or after the current selected date).
Click OK, then click OK again.
2- From the Registry:
You can adjust the
Hijri Calendar from your registry, by modifying the AddHijriDate key value at
Panel\International\ and setting it to one of the following values:
Subtract two days.
Subtract one day.
No adjustment is necessary. (If the date has not been adjusted,
this entry does not appear in the registry. If the date has been adjusted and
then restored to its original value, this entry appears in the registry with
Add one day.
Add two days.
Here is an example of
decrementing the current Hijri Date by two:
task bar go the Start menu \ Run and type regedit. Navigate down until you find
the International keys. Select AddHijriDate, right click and select Modify, and
in the Value data, write AddHijriDate – (the adjustment value), In this
example, you can set it to AddHijriDate – 2
Now, when you check your
system Hijri Date, you will find it has been decremented by two.
Windows MonthCalendar control presents an intuitive graphical interface
for users to view and set date information. The control displays a grid
containing the numbered days of the month, arranged in columns underneath the
days of the week. You can select a different month by clicking the arrow buttons
on either side of the month caption. Unlike the similar DateTimePicker
control, you can select a range of dates with this control; however, the DateTimePicker
control allows you to set times as well as dates. Unfortunately MonthCalendar
and hence the DateTimePicker do not currently support Hijri Dates, so
even if you set your calendar type to Hijri calendar in the Regional options,
you will still get the default Gregorian calendar. However, MonthCalendar
does support other Arabic calendars like the Arabic Gregorian calendar.
SQL Server 2000 stores the dates internally as two integers (4-byte integers for datetime,
and 2-byte integers for smalldatetime) that represent the date and time
Datetime, stores the date and time data in the Gregorian calendar
to an accuracy of one three-hundredth of a second (equivalent to 3.33
milliseconds or 0.00333 seconds).
Smalldatetime, stores the date and time data in the Gregorian
calendar from January 1, 1900, through June 6, 2079, with accuracy to the minute. smalldatetime
values with 29.998 seconds or lower are rounded down to the nearest minute;
values with 29.999 seconds or higher are rounded up to the nearest minute.
SQL Server rejects data that falls outside of these ranges. Irrespective of
what date format you give the SQL server, it will store the datetime in
its own internal format as a number, and therefore with no specific
international meaning. What determines how the Datetime value should be
displayed and in an international format, is the client tool. The client tool
receives the datetime value from the SQL Server and then converts it to
a string value in the desired format. However, SQL Server 2000 supports many
different locale-specific conversions that can be performed at the server
instead of relying on custom solutions from developers.
provides the CONVERT function which takes a data type, and an
expression. It can be used to convert the datetime number or value to a
string format. In this case the string format will be SQL’s default format. But
what if you want to display the date in a different format than the default?
The CONVERT function has an optional third parameter called style
to determine the date format. Some of the available styles can be found in the
Input (converting to datetime)
Output (converting to text)
0 or 100
mon dd yyyy hh:miAM (or PM)
dd mon yy
Mon dd, yy
9 or 109
Default + milliseconds
mon dd yyyy hh:mi:ss:mmmAM (or PM)
13 or 113
Europe default + milliseconds
dd mon yyyy hh:mm:ss:mmm(24h)
20 or 120
21 or 121
ODBC canonical + milliseconds
ISO8601 (no spaces)
dd mon yyyy hh:mi:ss:mmmAM
As can be
seen from the above table, SQL server supports conversion to Hijri date format
using the Kuwaiti algorithm. The two styles available in SQL Server 2000 to support
Hijri dates are:
· 130—Returns the date
using the Hijri calendar, in dd mon yyyy hh:mi:ss:mmmAM format.
· 131—Returns the date
using the Hijri calendar, in dd/mm/yy hh:mi:ss:mmmAM format.
example, to convert a Gregorian date to Hijri format with Transact-SQL, you
would use syntax such as the following:
SELECT CONVERT(nchar, GETDATE(), 131)
query will return a string such as the following in its result set:
reverse operation is also possible. The following syntax would be used to
convert a Hijri date to Gregorian format:
SELECT CONVERT(datetime, '5/07/1424 11:25:11:030AM', 131)
query would convert the date to SQL Server datetime type, which appears
in the SQL Query Analyzer as follows:
method is to do the conversions on the client side once a date value has been
functions such as DateDiff can also be used with Hijri Dates.
DATEDIFF ( datepart , startdate
, enddate ) takes two datetime
values and returns the difference in the specified datePart(the part of the
date you want to calculate the difference in, day , month or year). For the DateDiff
function to understand the Hijri dates, it has be converted to its datetime
equivalent value first. For example:
(datetime,'4/07/1424 11:25:11:030 AM',131), convert (datetime,'5/07/1424 11:25:11:030 AM',131))
DATEADD (datepart , number,
date ) returns a new datetime value based on adding an
interval to the specified date. It also takes a datetime value;
therefore you have to convert the Hijri Date format back to a date time value
convert back to Hijri, you convert the output of DateAdd with style 130, as
Convert (nchar, DateADD(d,21,convert
(datetime,'4/07/1424 11:25:11:030 AM',131)),130)
25 رجب 1424 11:25:11:030AM
you can see from the above output, the logical ordering is not correct. The problem can be considered a
general limitation of the 130 styles in the CONVERT function, although
you can work around it easily enough by adding the proper Unicode control
character in front of the string, as follows:
select nchar(8207)+ convert(nchar,DateADD(d,21,convert
(datetime,'4/07/1424 11:25:11:030 AM',131)),130)
DATEPART (datepart , date)
returns the part of the date requested by datepart. However,
datepart would return the part of the Gregorian date equivalent to the
Hijri date. For example:
Select datepart(d, convert (datetime,'4/07/1424 11:25:11:030 AM',131))
And it returns:
day 31 of the date 31/8/2003 in the Gregorian, equivalent to 4/7/1424 in Hijri.
Note that SQL Server does not use the regional calendar settings
included with Windows, and any adjustment made in the regional setting for the
Hijri date does not affect the conversion method in SQL Server.
Visual Studio .NET and Hijri Calendar
.NET Framework provides the Calendar Class as well as the following Calendar
implementations: GregorianCalendar and HijriCalendar and other
calendars. The CultureInfo Class has a CultureInfo.Calendar property
that retrieves a culture's default calendar. Some cultures support more than
one calendar. The CultureInfo.OptionalCalendars property retrieves the
optional calendars supported by a culture. For example, the Saudi Arabia
culture has six calendars, Hijri calendar (as default) plus five of different
Gregorian calendar types, as specified in the Regional Settings of the Control
The GregorianCalendar has different language versions of the Gregorian
calendar. Using the GregorianCalendar.CalendarType Property you can get
or set the GregorianCalendarTypes value that denotes the version of the
current GregorianCalendar. The date and time patterns associated with
the GregorianCalendar vary depending on the language. For Arabic cultures,
more language versions of the Gregorian calendar are available. For example,
you can use the French version of GregorianCalendar using the MiddleEastFrench
value. For more information see "GregorianCalendarTypes
Enumeration" in MSDN
Each CultureInfo supports
a set of calendars. The Calendar property returns the default calendar
for the culture, and the OptionalCalendars property returns an array
containing all the calendars supported by the culture. To change the calendar
used by a CultureInfo, set the Calendar property of CultureInfo.DateTimeFormat
to a new Calendar.
following example lists the calendar types of the Saudi Arabia
CultureInfo ci = new CultureInfo("ar-SA");
foreach (Calendar cal in ci.OptionalCalendars)
if(cal is GregorianCalendar)
GregorianCalendar gc = (GregorianCalendar)cal;
Using the Hijri Calendar
This implementation of the HijriCalendar class
adjusts the calendar date by adding or subtracting a value from zero to two
days to accommodate the date difference between countries/regions. That value
is stored in the HijriAdjustment property. If HijriAdjustment is not set
explicitly, it derives its value from the settings in Regional and Language
Options (or Regional Options or Regional Settings) in Control
Panel and is stored in the registry value AddHijriDate.
However, that information can change during the life of the AppDomain. The HijriCalendar class does not detect
changes in the system settings automatically.
You can set the culture’s calendar to
one of its supported calendar types. For
example, the Arabic cultures support the Hijri calendar, so, you can set the
Arabic culture calendar to Hijri calendar. The CultureInfo.Calendar is a
read-only property which gets the current calendar, but cannot be changed.
Instead, you can specify the calendar of the DateTimeFormat.Calendar of
the CultureInfo, as in the following code:
Create a CultureInfo object for Saudi Arabia.
CultureInfo sa = new CultureInfo("ar-SA");
sa.DateTimeFormat.Calendar = new HijriCalendar();
You can perform any operation with Hijri dates in the same way,
such as displaying Hijri and converting Hijri calendar to/from Gregorian or
MonthCalendar and DateTimePicker Windows Controls
Studio .NET, you can reference many of the existing windows controls including
the previously mentioned MonthCalendar and the DateTimePicker, to display the system calendar.
Calendar Web Control
Calendar control displays a traditional one-month calendar on your Web
Forms pages. Users can use the calendar to view and select dates. The web calendar
control uses the default user locale specified from the Regional options in the
place a calendar control inside your web application, open the tool box’ web
forms’ controls, scroll down until you find the Calendar control, click
on it and drop it on the web page. To have it display the Hijri Calendar in the
web form, you also need to set the web page’s Culture property to any
Arabic language and the same for the Web page’s uiCulture, after setting
the user locale in the control panel:
For proper RTL display, scroll down the properties to the
dir property and choose rtl.
When you run you get a web page, with your Hijri Calendar:
Converting from Gregorian to Hijri date
Using Datetime.ToString(ByVal format As String ,
ByVal provider As IFormatProvider):
Converts the value of this Datetime instance to its
equivalent string representation using the specified format and culture-specific format information.
The following Windows application
example converts a date from Gregorian to Hijri and displays it:
dt = Convert.ToDateTime("1/09/2003");
HijriDTFI = new System.Globalization.CultureInfo("ar-EG",false).DateTimeFormat;
HijriDTFI.Calendar = new System.Globalization.HijriCalendar();
HijriDTFI),”Hijri Date”, MessageBoxButtons.OK,
The output is:
Converting from Hijri to Gregorian
1- Using Datetime.ToString:
following example converts date from Hijri to Gregorian:
DateTime dt = new DateTime(1422,
1,1, new HijriCalendar());
The output is:
1/9/2003 or 1/9/2003 (according to your current
Converts the given
date string in whichever format or culture and converts it to its equivalent Datetime
value or number.
Dim ResultFrm As New Result()
Dim MyDate As DateTime
Dim CtHijri As New CultureInfo("ar-EG")
= New System.Globalization.HijriCalendar()
MyDate = System.DateTime.Parse(“5/07/1424 “, CtHijri,
paper, we have tried to give you an overview of Microsoft’s support to Hijri
Calendars in Windows XP, SQL Server 2000, and Visual Studio .NET. By the time
you read this paper, there would probably be more and more international
features and Arabic support incorporated in those and many others of Microsoft
For More Information
SQL® Server 2000. Arabic Language Support - White Paper.
Studio .NET® With Arabic Language Support