diff --git a/src/timezone.c b/src/timezone.c
index f8d192df..89c44895 100644
--- a/src/timezone.c
+++ b/src/timezone.c
@@ -38,9 +38,10 @@
 
 #include "connman.h"
 
-#define ETC_SYSCONFIG_CLOCK	"/etc/sysconfig/clock"
-#define USR_SHARE_ZONEINFO	"/usr/share/zoneinfo"
-#define USR_SHARE_ZONEINFO_MAP	USR_SHARE_ZONEINFO "/zone1970.tab"
+#define ETC_SYSCONFIG_CLOCK		"/etc/sysconfig/clock"
+#define USR_SHARE_ZONEINFO		"/usr/share/zoneinfo"
+#define USR_SHARE_ZONEINFO_MAP		USR_SHARE_ZONEINFO "/zone1970.tab"
+#define USR_SHARE_ZONEINFO_MAP_OLD	USR_SHARE_ZONEINFO "/zone.tab"
 
 static char *read_key_file(const char *pathname, const char *key)
 {
@@ -115,12 +116,17 @@ static char *read_key_file(const char *pathname, const char *key)
 }
 
 static int compare_file(void *src_map, struct stat *src_st,
-						const char *pathname)
+				const char *real_path, const char *pathname)
 {
 	struct stat dst_st;
 	void *dst_map;
 	int fd, result;
 
+	DBG("real path %s path name %s", real_path, pathname);
+
+	if (real_path && g_strcmp0(real_path, pathname))
+		return -1;
+
 	fd = open(pathname, O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
 		return -1;
@@ -151,7 +157,8 @@ static int compare_file(void *src_map, struct stat *src_st,
 }
 
 static char *find_origin(void *src_map, struct stat *src_st,
-				const char *basepath, const char *subpath)
+				const char* real_path, const char *basepath,
+				const char *subpath)
 {
 	DIR *dir;
 	struct dirent *d;
@@ -186,7 +193,8 @@ static char *find_origin(void *src_map, struct stat *src_st,
 						"%s/%s/%s", basepath,
 							subpath, d->d_name);
 
-			if (compare_file(src_map, src_st, pathname) == 0) {
+			if (compare_file(src_map, src_st, real_path, pathname)
+									== 0) {
 				if (!subpath)
 					str = g_strdup(d->d_name);
 				else
@@ -214,7 +222,8 @@ static char *find_origin(void *src_map, struct stat *src_st,
 				snprintf(pathname, sizeof(pathname),
 						"%s/%s", subpath, d->d_name);
 
-			str = find_origin(src_map, src_st, basepath, pathname);
+			str = find_origin(src_map, src_st, real_path, basepath,
+						pathname);
 			if (str) {
 				closedir(dir);
 				return str;
@@ -228,7 +237,52 @@ static char *find_origin(void *src_map, struct stat *src_st,
 	return NULL;
 }
 
-static char *get_timezone_alpha2(const char *zone)
+/* TZ map file format: Countrycodes Coordinates TZ Comments */
+enum tz_map_item {
+	TZ_MAP_ITEM_ISO3166 = 0,
+	TZ_MAP_ITEM_COORDINATE = 1,
+	TZ_MAP_ITEM_TIMEZONE = 2,
+	TZ_MAP_ITEM_COMMENT = 3,
+};
+
+static bool iso3166_matches(const char *codes, const char *iso3166)
+{
+	gchar **tokens;
+	guint len;
+	guint i;
+	bool ret = false;
+
+	if (!codes || !iso3166)
+		return false;
+
+	tokens = g_strsplit(codes, ",", -1);
+	if (!tokens)
+		return false;
+
+	len = g_strv_length(tokens);
+	if (len < 2) {
+		g_strfreev(tokens);
+		return false;
+	}
+
+	DBG("search %s from %s", iso3166, codes);
+
+	for (i = 0; i < len; i++) {
+		DBG("#%d %s", i, tokens[i]);
+
+		if (!g_strcmp0(tokens[i], iso3166)) {
+			ret = true;
+			break;
+		}
+	}
+
+	g_strfreev(tokens);
+
+	return ret;
+}
+
+static char *get_timezone_alpha2(const char *zone, const char *mapfile,
+						enum tz_map_item map_item)
 {
 	GIOChannel *channel;
 	struct stat st;
@@ -236,15 +290,15 @@ static char *get_timezone_alpha2(const char *zone)
 	char *line;
 	char *alpha2 = NULL;
 	gsize len;
+	bool found = false;
 	int fd;
 
 	if (!zone)
 		return NULL;
 
-	fd = open(USR_SHARE_ZONEINFO_MAP, O_RDONLY | O_CLOEXEC);
+	fd = open(mapfile, O_RDONLY | O_CLOEXEC);
 	if (fd < 0) {
-		connman_warn("failed to open zoneinfo map %s",
-							USR_SHARE_ZONEINFO_MAP);
+		connman_warn("failed to open zoneinfo map %s", mapfile);
 		return NULL;
 	}
 
@@ -256,23 +310,23 @@ static char *get_timezone_alpha2(const char *zone)
 
 	channel = g_io_channel_unix_new(fd);
 	if (!channel) {
-		connman_warn("failed to create io channel for %s",
-							USR_SHARE_ZONEINFO_MAP);
+		connman_warn("failed to create io channel for %s", mapfile);
 		close(fd);
 		return NULL;
 	}
 
-	DBG("read %s for %s", USR_SHARE_ZONEINFO_MAP, zone);
+	DBG("read %s for %s", mapfile, zone);
 	g_io_channel_set_encoding(channel, "UTF-8", NULL);
 
 	while (g_io_channel_read_line(channel, &line, &len, NULL, NULL) ==
 							G_IO_STATUS_NORMAL) {
+		found = false;
+
 		if (!line || !*line || *line == '#' || *line == '\n') {
 			g_free(line);
 			continue;
 		}
 
-		/* File format: Countrycodes Coordinates TZ Comments */
 		tokens = g_strsplit_set(line, " \t", 4);
 		if (!tokens) {
 			connman_warn("line %s failed to parse", line);
@@ -280,13 +334,35 @@ static char *get_timezone_alpha2(const char *zone)
 			continue;
 		}
 
-		if (g_strv_length(tokens) >= 3 && !g_strcmp0(
-						g_strstrip(tokens[2]), zone)) {
+		if (g_strv_length(tokens) >= 3) {
+			switch (map_item) {
+			case TZ_MAP_ITEM_ISO3166:
+
+				if (!g_strcmp0(tokens[0], zone)) {
+					found = true;
+					break;
+				}
+
+				if (iso3166_matches(tokens[0], zone))
+					found = true;
+				break;
+			case TZ_MAP_ITEM_COORDINATE:
+				break;
+			case TZ_MAP_ITEM_TIMEZONE:
+				if (!g_strcmp0(g_strstrip(tokens[2]), zone))
+					found = true;
+				break;
+			case TZ_MAP_ITEM_COMMENT:
+				break;
+			}
+
 			/*
 			 * Multiple country codes can be listed, use the first
-			 * 2 chars.
+			 * 2 chars as backends such as gsupplicant support only
+			 * the main country code.
 			 */
-			alpha2 = g_strndup(g_strstrip(tokens[0]), 2);
+			if (found)
+				alpha2 = g_strndup(g_strstrip(tokens[0]), 2);
 		}
 
 		g_strfreev(tokens);
@@ -300,9 +376,8 @@ static char *get_timezone_alpha2(const char *zone)
 			} else {
 				DBG("Zone %s ISO3166 country code %s", zone,
 									alpha2);
+				break;
 			}
-
-			break;
 		}
 	}
 
@@ -312,6 +387,44 @@ static char *get_timezone_alpha2(const char *zone)
 	return alpha2;
 }
 
+static char *try_get_timezone_alpha2(const char *zone)
+{
+	char *alpha2;
+	char *alpha2_old;
+
+	/* First try the official map */
+	alpha2 = get_timezone_alpha2(zone, USR_SHARE_ZONEINFO_MAP,
+							TZ_MAP_ITEM_TIMEZONE);
+	if (alpha2)
+		return alpha2;
+
+	DBG("%s not found in %s", zone, USR_SHARE_ZONEINFO_MAP);
+
+	/* The zone was not found in official map, try with deprecated */
+	alpha2_old = get_timezone_alpha2(zone, USR_SHARE_ZONEINFO_MAP_OLD,
+							TZ_MAP_ITEM_TIMEZONE);
+	if (!alpha2_old) {
+		DBG("%s not found in %s", zone, USR_SHARE_ZONEINFO_MAP_OLD);
+		return NULL;
+	}
+
+	/*
+	 * Found from deprecated, try to get main region code from official new
+	 * map using the iso3166 search. This is because some of the codes
+	 * defined in the deprecated are not supported by the backends, e.g.,
+	 * gsupplicant and the main code should be used.
+	 */
+	alpha2 = get_timezone_alpha2(alpha2_old, USR_SHARE_ZONEINFO_MAP,
+							TZ_MAP_ITEM_ISO3166);
+
+	DBG("%s -> ISO3166 %s found in %s as %s", zone, alpha2_old,
+						USR_SHARE_ZONEINFO_MAP, alpha2);
+
+	g_free(alpha2_old);
+
+	return alpha2;
+}
+
 char *__connman_timezone_lookup(void)
 {
 	struct stat st;
@@ -319,13 +432,16 @@ char *__connman_timezone_lookup(void)
 	int fd;
 	char *zone;
 	char *alpha2;
+	const char *local_time;
+	char real_path[PATH_MAX];
 
 	zone = read_key_file(ETC_SYSCONFIG_CLOCK, "ZONE");
 
 	DBG("sysconfig zone %s", zone);
 
-	fd = open(connman_setting_get_string("Localtime"),
-							O_RDONLY | O_CLOEXEC);
+	local_time = connman_setting_get_string("Localtime");
+
+	fd = open(local_time, O_RDONLY | O_CLOEXEC);
 	if (fd < 0) {
 		g_free(zone);
 		return NULL;
@@ -334,6 +450,15 @@ char *__connman_timezone_lookup(void)
 	if (fstat(fd, &st) < 0)
 		goto done;
 
+	if (!realpath(local_time, real_path)) {
+		connman_error("Failed to get real path of %s: %d/%s",
+					local_time, errno, strerror(errno));
+		g_free(zone);
+		close(fd);
+
+		return NULL;
+	}
+
 	if (S_ISREG(st.st_mode)) {
 		map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
 		if (!map || map == MAP_FAILED) {
@@ -349,14 +474,15 @@ char *__connman_timezone_lookup(void)
 			snprintf(pathname, PATH_MAX, "%s/%s",
 						USR_SHARE_ZONEINFO, zone);
 
-			if (compare_file(map, &st, pathname) != 0) {
+			if (compare_file(map, &st, NULL, pathname) != 0) {
 				g_free(zone);
 				zone = NULL;
 			}
 		}
 
 		if (!zone)
-			zone = find_origin(map, &st, USR_SHARE_ZONEINFO, NULL);
+			zone = find_origin(map, &st, real_path,
+						USR_SHARE_ZONEINFO, NULL);
 
 		munmap(map, st.st_size);
 	} else {
@@ -370,7 +496,7 @@ done:
 	DBG("localtime zone %s", zone);
 
 	if (connman_setting_get_bool("RegdomFollowsTimezone")) {
-		alpha2 = get_timezone_alpha2(zone);
+		alpha2 = try_get_timezone_alpha2(zone);
 		if (alpha2) {
 			DBG("change regdom to %s", alpha2);
 			connman_technology_set_regdom(alpha2);
