Date and time localization

Date and time localization is quite an important topic when it comes to developing applications and software systems in multiple languages. Date and time are written and read in different ways in different countries. Furthermore, in software development, there are a numerous technologies, languages, and frameworks that we can use to implement localization. In this article, we are going to discuss some of the methods that make the date and time localization process easier.

Introduction

It’s no secret that people in different countries write the date and time in a certain way. For instance, in the US, they specify the month first, followed by the day, and then the year. Each component is also separated with a slash, which gives us mm/dd/yyyy, for example: 09/01/2021, which would be September 1, 2021. However, if you show this date to a person from, say, Russia, s/he would think that 09 is the day and the 01 is the month. That’s because in CIS countries, the day goes before the month and usually each component is separated with dots: dd.mm.yyyy. Residents of some Asian countries, as well as Iran, write the year first, followed by the month, and then the day: yyyy-mm-dd.

Moreover, we have different time formats; in some countries people tend to use a 12-hour format and append am/pm, whereas in others the standard is the 24-hour format. Therefore, it’s very important to properly localize date and time based on the currently set locale.

Date and time localization methods in Python

First of all, let’s talk about how we can convert one date-time format into another. As you can see in this article, there are so many date and time formats. For example, you could have 1997/01/27 18:30 or 20/01/1997 18:30. Read the following code snippet carefully to understand how to convert date and time between different formats in Python:

from datetime import datetime
 
dateTime = datetime.now()
datetime_str_1 = dateTime.strftime("%B %d, %Y %A, %H:%M:%S")
datetime_str_2 = dateTime.strftime("%Y/%m/%d, %H:%M:%S")
print(datetime_str_1)
print(datetime_str_2)

Here, we have used the Python package called datetime. That package has a function called now() which returns the current time. So in the above code, the same time is written in two different formats. When you execute this code, you will get the following result:

July 18, 2021 Sunday, 23:29:19

2021/07/18, 23:29:19

Using this strftime function, you can convert a given time to most of the formats being used in the world.

However, you need to keep in mind that time is always relative. For instance, the current time in the UK is different from the current time in Japan. To overcome this problem, developers have come up with the concept of the Coordinated Universal Time (UTC) timestamp which is the number of seconds from the UNIX epoch. But obviously, in software systems, we don’t keep time in UTC, and we convert it into local time. In order to convert UTC to local time, we need to add the time offset to UTC.

E.g.: UTC -> 2021–08–13T10:23:40

Local time -> 2021–08–13T10:23:40+07:00

The format of parsing the time with the offset is %Y-%m-%dT%H:%M:%S%z. Here %z represents the offset. To have a better understanding of this, take a look at this code snippet:

import datetime
import dateutil.parser
format = '%Y-%m-%dT%H:%M:%S%z'
date_to_parse = '2021-07-21T20:40:21-06:00'
dt = dateutil.parser.parse(date_to_parse)
print(dt)

Now you know what the offset is and how can we parse the date with the offset. However, since the local time only helps to identify the time on the given date, we cannot use it for calculations related to locations. This is where the time zone comes in. Time zones are represented by continent name plus location name. For a complete understanding of time zones, read this article. Now, let’s see how we can use these time zones in the code:

import datetime
import pytz
naiveDate = datetime.datetime(2021, 10, 21, 13, 21, 25)
utc = pytz.UTC
time_zone = pytz.timezone('America/Los_Angeles')
localizedDate = utc.localize(naiveDate)
increasedDate = localizedDate + datetime.timedelta(days=10)
d = increasedDate.astimezone(time_zone)

Here we have used the pytz python module to handle time zone details in Python. Make sure that you use UTC for all the time-related calculations and then convert that into local time because, as already discussed, local time is always relative. In the example above, we have used the America/Los_Angeles time zone.

Another important date and time localization method that you should understand is that using the locale. Actually, the locale is a framework to switch between multiple languages. Take a look at the below code snippet for a better idea of this:

import time
import locale
locale.setlocale(locale.LC_TIME, 'en_US.UTF-8')
d1= time.strftime("%A, %d. %B %Y %I:%M%p")
 
locale.setlocale(locale.LC_ALL, 'si_LK.UTF8')
d2= dt.strftime("%A, %d. %B %Y %I:%M%p")

As you can see, we have imported two Python modules: time and locale. You also need to provide the actual locale, or you can use the default locale as well. In this instance, en_US is the locale in the US and si_LK indicates the locale in Sri Lanka. So the above code will output the following result:

Monday, 19. July 2021 02:20AM

සඳුදා, 19. ජූලි 2021 02:19පෙ.ව

The first result shows my current local time in the en_US locale. The next result gives my current time in locale si_LK. Si indicates the language ‘Sinhala’ which is used in Sri Lanka. Note that when you change the locale, the language of the output changes accordingly.

Now we know the basic concepts of date and time localization such as offset, time zone, and locales in Python. Next, we’ll take a look at how we can enable date and time localization in Java.

Date and time localization in Java

First of all, let’s see how we can format the time and date in Java. To do this, we can use the Java class DateFormat. Let’s discover how we can show the date and time in a short format. Read the following code snippet:

DateFormat shortDateFormat = DateFormat.getDateInstance( DateFormat.SHORT, Locale.US);
String s = "27/01/1997";
try {
    Date date = shortDAteFormat.parse(s);
    System.out.println(date);
} catch (ParseException e) {
     System.out.println("Exception!!!");
}

Here we have used the date instance in the format of DateFormat.SHORT. Also, we can provide the required locale in the same function. In this example, we have used the US locale. Here’s the result:

Mon Jan 27 00:00:00 IST 1997

Similarly, we can have several other formats such as, LONG, FULL, etc. Other than that, you can customize the date and time parsing format by using the DateFormat and SimpleDateFormat Java classes. Take a look at the example below:

DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
System.out.println(dateFormat.parse("01/02/1997"));

Make sure that you have imported simpleDateFormat as shown here:

import java.text.SimpleDateFormat;

When we execute the above code snippet we are getting the following output:

Sat Feb 01 00:00:00 IST 1997

Simple, right? Now we know one method of parsing different date formats. Next, we are going to check out how to output date and time in different patterns. We can use the same SimpleDateFomat Java package for this. Let’s take a look at this example:

String date_pattern = "MM-dd-yyyy";
SimpleDateFormat simple_date_Format = new SimpleDateFormat(date_pattern);
String date = simple_date_Format.format(new Date());
System.out.println(date);

Here, we have provided the date pattern inside the date_pattern variable.

Next, let’s see how we can deal with the time zones in Java. In Java 8, the time zone details are handled by the ZonedDateTime class. In this class, the time zone is indicated as the number of hours. You can take the current existing time zone by using the now() function in the ZonedDateTime class as follows:

System.out.println(ZonedDateTime.now());

Here’s the output:

2021-07-20T00:02:03.232139+05:30[Asia/Colombo]

You can make a ZonedDateTime class instance using the of() method with all the year, month, date, hour, minute, second, nano-second, and time zone details. Take a look at the following code snippet for an idea of how to make a zonedDateTime instance:

ZonedDateTime.of(
         2021, 11, 4, 10, 25, 20,
         30000, ZoneId.systemDefault()
       );

Here we have set the time zone with the ZoneId.systemDefault() method. This zonedDateTime class contains new options such as, ZoneID, ZoneOffset, ZonedDateTime, OffsetDateTime, and OffsetTime.

TimeZone is another class for handling time zones in Java. Let’s see how to set and get time zones in Java with the TimeZone Java class. First, you need to import the time zone package as follows:

import java.util.TimeZone;

Now let’s move on to the implementation:

Date now = new Date();
 
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
System.out.println(now);
 
TimeZone.setDefault( TimeZone.getTimeZone("UTC"));
System.out.println(now);
 
TimeZone.setDefault( TimeZone.getTimeZone("GMT"));
System.out.println(now);

Here, we have:

  • Obtained the current date and time with time zone.
  • Got the current time in different time zones by providing the actual time zone.

The output of the above code is:

date time localization

 

LocalDate class in Java 8

LocalDate is another important class introduced in Java 8. This class is immutable and thread-safe. Furthermore, LocalDate represents the date in ISO format, for example: 2021-01-01. So let’s see how to perform localization with the Java LocalDate class. 

You can get the current date with the now() function in the LocalDate class:

LocalDate currentDate = LocalDate.now();

You can also use the parse() method to get an instance of the LocalDate class. You’ll need to provide a parseable string as input and then the parse function will return the local date and time:

LocalDate.parse("2020-01-21");

A special feature of this class is that it can perform several date-related calculations with built-in functions, such as plusDays() and minus(), with ease. Let’s see some examples.

With the plusDays() function, you can get a future day by adding a certain number of days to a given date. Check out the following example for a better understanding:

LocalDate twoDaysFromToday = LocalDate.now().plusDays(2);
System.out.println("Two days from today: " + twoDaysFromToday);

Output:

Two days from today: 2021 : 08 : 05

 

To subtract time from a given date, use the minus() function. In the below example, it will return the date of two months prior to today:

LocalDate somePreviousDay = LocalDate.now().minus(2, ChronoUnit.MONTHS);

Moreover, we can easily get a specific day of the week, the first day of the month, and check whether a given year is a leap year:

import java.time.*;
import java.time.temporal.TemporalAdjusters;

public class Main {
    public static void main(String[] args) {

        DayOfWeek day = LocalDate.parse("2021-02-11").getDayOfWeek(); 
        LocalDate firstDayOfMonth = LocalDate.parse("2021-03-30").with(TemporalAdjusters.firstDayOfMonth()); 
        boolean leapYearCheck = LocalDate.parse("2021-02-11").isLeapYear(); 

        System.out.println("day : " + day);
        System.out.println("firstDayOfMonth : " + firstDayOfMonth);
        System.out.println("leapYearCheck : " + leapYearCheck);
    }
}

Here’s the output:

So as you see, there are several methods for localizing date and time in Java. Next, we are going to see how we can handle date and time localization in JavaScript.

Date and time localization in JavaScript

In JavaScript, there are numerous methods for localizing dates and times. Let’s see how we can handle date and time localization in vanilla JavaScript — you’ll use more or less the same methods in JS frameworks as well.

In JavaScript, there are basically three different date input formats:

  • ISO Date
  • Long Date
  • Short Date

Regardless of the input date format, JavaScript outputs date as a full string text. You can see this in the following code snippet:

const date = new Date()
console.log(date)

Here’s the output:

Tue Jul 20 2021 22:19:18 GMT+0530 (India Standard Time) 

As you can see, it returns the date as a string including the time zone. 

In JavaScript, the ISO date format can be written according to the syntax: YYYY-MM-DD. For instance, the date 2021-01-21 is written in the ISO date format:

const date = new Date("2020-02-01");
console.log(date);

Output:

Sat Feb 01 2020 05:30:00 GMT+0530 (India Standard Time)

 

In the ISO date format, we can omit some components. For example, providing only the year and month:

const date = new Date("2020-02");
console.log(date)

Output:

Sat Feb 01 2020 05:30:00 GMT+0530 (India Standard Time)

Only the year:

const date = new Date("2020");
console.log(date)

Output:

Wed Jan 01 2020 05:30:00 GMT+0530 (India Standard Time)

Providing the date and time:

const date = new Date("2020-02-20T12:00:00Z");
console.log(date)

Output:

Thu Feb 20 2020 17:30:00 GMT+0530 (India Standard Time)

You may have noticed that if we are giving only the year, the output assumes the month is the 1st month of the year and the date is the first date of the month. For example, if you give 2014, it is interpreted as 2014-01-01. According to the same concept, when we give 2014-01, it is interpreted as 2014-01-01. 

More JavaScript date formats

Let’s briefly discuss the other JavaScript date formats as well. The syntax of the short date format is MM/DD/YYYY. We can write it as:

const date = new Date("02/21/2020");
console.log(date);

In the long date format, the syntax of the date is MMM DD YYYY. Here, the month and date can be provided in any order. For example, both Jan 21 2020 and 21 Jan 2020 are valid formats. Other than that, you can use any of the long or short names of the month. 

Another important aspect of the long date format is that the month’s name is case sensitive. ‘January’ and ‘JANUARY’ are both interpreted in the same way. 

In the next part of this section, we are going to talk about how we can handle date and time according to locale. For this, several functions were introduced in ES6 — let’s briefly discuss those.

Handling date and time according to locale in JavaScript

Date.prototype.toLocaleDateString() — this method returns the date according to a given locale. It also explicitly changes the language based on the given locale. Take a look at this example:

const event = new Date(Date.UTC(2021, 07, 08, 2, 0, 0));
 
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
 
console.log(event.toLocaleDateString('de-DE', options));
console.log(event.toLocaleDateString('ar-EG', options));
console.log(event.toLocaleDateString(undefined, options));

On the first line, we have entered the date in UTC, which returns the number of milliseconds passed from the start of the UNIX epoch. For instance, Date.UTC(2021, 07, 08,2,0,0) returns 1628388000000.

Then we convert it to a Date object. The value held in the event variable is:

Sun Aug 08 2021 07:30:00 GMT+0530 (India Standard Time)

 

Next, we have created an object called options to indicate the return values of each date and time in a given locale.

Then we use the toLocaleDateString method. First, we change the locale to de-DE (German language). The output is:

Sonntag, 8. August 2021

 

It returns the weekday, day, month, and year in German.

The next locale is ar-EG (Arabic language).

The output is:

الأحد، ٨ أغسطس ٢٠٢١

 

If you don’t provide any locale to the toLocalDateString() function, a default locale will be utilized. Since my current default locale is en-US, I’ll get the following output:

Sunday, August 8, 2021

 

Intl.DateTimeFormat() — this is also an important function that was introduced in ES6 for date and time formatting according to the specified locale. Let’s see another example:

const date = new Date(Date.UTC(2021, 12, 20, 3, 23, 16, 750));
console.log(new Intl.DateTimeFormat('en-US').format(date));
console.log(new Intl.DateTimeFormat(['ban', 'id']).format(date));
console.log(new Intl.DateTimeFormat('en-GB', { dateStyle: 'full', timeStyle: 'long' }).format(date));

Similarly to the previous example, we have created a Date object. The first locale we have provided is en-US. We’re converting the given date-time object using the default format using the provided locale. The output is:

1/20/2022

 

In the second console.log function, we have specified the default date format for the language with a fallback language set to Indonesian (id). The output is:

20/1/2022 

 

Finally, we have specified the date and time format using “style” options. Some of the style options you can use are full, long, medium, and so on. Since the style is full and the language is English, we get the following output:

Thursday, 20 January 2022 at 08:53:16 GMT+5:30

 

Date and time localization in PHP

Next, we will discuss how to deal with date and time localization in PHP. First, let’s discover how we can format date and time. To do this, we can use the date() function. It converts the timestamp to a more readable date and time. The syntax of the date() function is as follows.

date(format, timestamp)

If we don’t provide the timestamp, it returns the current date and time. Take a look at the below example:

<?php
$today_date = date("d/m/Y");
echo $today_date;
?>

As you see here we haven’t provided the timestamp. So it will return the current date in the given format. Here’s the output:

20/07/2021

 

Now let’s see another example that contains time as well:

<?php
echo date("h:i:s") ;
echo date("F d, Y h:i:s A");
?>

The output is:

08:27:08

July 20, 2021 08:27:08 PM

 

When you are using date and time formatting in PHP, it is very important to know the formatting characters for different units such as date, time, long month name, seconds, etc. You can find these characters in this article. 

Now, let’s see how we can get the date and time based on the locale. To achieve this, we can use the strftime() function. Please note that you can change the current locale with the setlocale() function. Here’s an example:

<?php
setlocale(LC_TIME, "en_US");
echo strftime("English- %c");
?>

Here’s the output:

English- Tue Jul 20 20:46:54 2021

These are the basics of date and time localization in PHP. You can refer to this documentation article to get a more complete understanding of this function.

Date and time localization in Ruby on Rails

To properly localize date and time in Ruby on Rails, use the localize method aliased as l. It’s also recommended to add the rails-i18n gem into the Gemfile that has the locale data for different languages. For example, it has translated names of the months, pluralization rules, and other useful stuff.

The l method is very similar to Ruby’s strftime. You can provide a predefined format or construct your own.

For instance, here’s how to use the :long format:

l post.created_at, format: :long

Depending on the locale, this format will be a bit different but in general it displays your date and time in the following way: “full month name – day – year – hours – minutes.” For example:

January 23, 2021 23:05

 

You can also specify your very own format:

l post.created_at, format: "%B %Y"

The placeholders are similar to the ones listed in the strftime docs.

On top of that, you can create custom formats in your translation files. To achieve this, open a translation file inside the config/locales folder and add something like this:

en:
  time:
    formats:
      very_short: "%H:%M"

Now you have a very_short format available for the English locale. It’s important to define the new format for all other locales as well.

To learn more about the Rails internationalization and localization process in general and how to add a locale switcher to your app, you can check out our step-by-step tutorial.

Summary

So, in this article, we’ve discussed how to handle date and time localization in several programming languages such as Python, PHP, Java, JavaScript, and Ruby. If you’d like to learn more about i18n and l10n processes in various technologies, you might be interested in checking out our collection of tutorials which lists how-tos on many popular languages and technologies. Thank you for your attention and happy coding!

Related posts

Sign up to our newsletter

Get the latest articles on all things data delivered straight to your inbox.

Read also
Localization made easy. Why wait?
The preferred localization tool of 2000+ companies