├── LICENSE ├── NSTimeZone+ISCLLocation.h ├── NSTimeZone+ISCLLocation.m ├── README.md └── zone.tab /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 IOSPIRIT GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /NSTimeZone+ISCLLocation.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimeZone+ISCLLocation.h 3 | // ISKit 4 | // 5 | // Created by Felix Schwarz on 30.03.15. 6 | // Copyright (c) 2015 IOSPIRIT GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSTimeZone (ISCLLocation) 13 | 14 | /** 15 | Preloads location/time zone table and keeps it in memory. Use this when you're performing a lot of different location lookups or many ISO 3166 country code lookups. 16 | */ 17 | + (void)preloadTimeZoneLocationTable; 18 | 19 | /** 20 | Looks up and returns the location for this timezone instance. 21 | 22 | @return Location for this timezone. nil if the timezone is not in the database. 23 | */ 24 | - (CLLocation *)approximateLocation; 25 | 26 | /** 27 | Looks up and returns the ISO 3166 country code for this timezone instance. 28 | 29 | @return ISO 3166 country code for this timezone. nil if the timezone is not in the database. 30 | */ 31 | - (NSString *)ISO3166CountryCode; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /NSTimeZone+ISCLLocation.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimeZone+ISCLLocation.m 3 | // ISKit 4 | // 5 | // Created by Felix Schwarz on 30.03.15. 6 | // Copyright (c) 2015 IOSPIRIT GmbH. All rights reserved. 7 | // 8 | 9 | #import "NSTimeZone+ISCLLocation.h" 10 | 11 | // Keys used in lookup table 12 | static NSString *kISTZCLCountryCodeKey = @"CountryCode"; 13 | static NSString *kISTZCLCoordinatesKey = @"Coordinates"; 14 | static NSString *kISTZCLTimeZoneNameKey = @"TimeZone"; 15 | 16 | // Global lookup table 17 | static NSDictionary *sISTimeZoneLocationDict = nil; 18 | static NSMutableDictionary *sISTimeZoneLocationCacheDict = nil; 19 | static NSMutableDictionary *sISTimeZoneCountryCodeCacheDict = nil; 20 | 21 | // Class to help find the bundle from which this category originates to automatically locate the "zone.tab" file 22 | @interface ISNSTimeZoneCLLocationCategoryFinder : NSObject 23 | @end 24 | 25 | @implementation ISNSTimeZoneCLLocationCategoryFinder 26 | @end 27 | 28 | // Implementation 29 | @implementation NSTimeZone (ISCLLocation) 30 | 31 | #pragma mark - Tools 32 | + (double)IS_degreesFromISO6709String:(NSString *)isoString 33 | { 34 | double resultDegrees = 0; 35 | NSString *plusMinusString=nil, *degreesString=nil, *minutesString=nil, *secondsString=nil; 36 | 37 | /* 38 | # 2. Latitude and longitude of the area's principal location 39 | # in ISO 6709 sign-degrees-minutes-seconds format, 40 | # either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, 41 | # first latitude (+ is north), then longitude (+ is east). 42 | */ 43 | 44 | if (isoString.length >= 5) 45 | { 46 | plusMinusString = [isoString substringToIndex:1]; 47 | 48 | switch (isoString.length) 49 | { 50 | case 5: 51 | // +-DDMM 52 | degreesString = [isoString substringWithRange:NSMakeRange(1, 2)]; 53 | minutesString = [isoString substringWithRange:NSMakeRange(3, 2)]; 54 | break; 55 | 56 | case 6: 57 | // +-DDDMM 58 | degreesString = [isoString substringWithRange:NSMakeRange(1, 3)]; 59 | minutesString = [isoString substringWithRange:NSMakeRange(4, 2)]; 60 | break; 61 | 62 | case 7: 63 | // +-DDMMSS 64 | degreesString = [isoString substringWithRange:NSMakeRange(1, 2)]; 65 | minutesString = [isoString substringWithRange:NSMakeRange(3, 2)]; 66 | secondsString = [isoString substringWithRange:NSMakeRange(5, 2)]; 67 | break; 68 | 69 | case 8: 70 | // +-DDDMMSS 71 | degreesString = [isoString substringWithRange:NSMakeRange(1, 3)]; 72 | minutesString = [isoString substringWithRange:NSMakeRange(4, 2)]; 73 | secondsString = [isoString substringWithRange:NSMakeRange(6, 2)]; 74 | break; 75 | } 76 | 77 | if (degreesString!=nil) 78 | { 79 | resultDegrees += [degreesString doubleValue]; 80 | } 81 | 82 | if (minutesString!=nil) 83 | { 84 | resultDegrees += ([minutesString doubleValue]/(double)60.0); 85 | } 86 | 87 | if (secondsString!=nil) 88 | { 89 | resultDegrees += ([secondsString doubleValue]/(double)3600.0); 90 | } 91 | 92 | if ([plusMinusString isEqual:@"-"]) 93 | { 94 | resultDegrees *= (double)-1.0; 95 | } 96 | } 97 | 98 | return (resultDegrees); 99 | } 100 | 101 | + (NSDictionary *)IS_recordsByTimeZoneFromZoneTabFile:(NSURL *)zoneTabURL onlyZoneName:(NSString *)onlyZoneName 102 | { 103 | NSString *zoneTabContents = nil; 104 | NSError *error = nil; 105 | NSMutableDictionary *recordsByTimeZone = nil; 106 | 107 | if (zoneTabURL == nil) 108 | { 109 | @synchronized(self) 110 | { 111 | if (sISTimeZoneLocationDict != nil) 112 | { 113 | return ([[sISTimeZoneLocationDict retain] autorelease]); 114 | } 115 | } 116 | 117 | zoneTabURL = [[NSBundle bundleForClass:[ISNSTimeZoneCLLocationCategoryFinder class]] URLForResource:@"zone" withExtension:@"tab"]; 118 | } 119 | 120 | if ((zoneTabContents = [[NSString alloc] initWithContentsOfURL:zoneTabURL encoding:NSUTF8StringEncoding error:&error]) != nil) 121 | { 122 | NSString *tab = [NSString stringWithFormat:@"\t"]; 123 | NSArray *zoneTabLines = nil; 124 | 125 | recordsByTimeZone = [NSMutableDictionary dictionary]; 126 | 127 | // Split in lines 128 | zoneTabLines = [zoneTabContents componentsSeparatedByString:[NSString stringWithFormat:@"\n"]]; 129 | 130 | // Parse lines 131 | for (NSString *zoneTabLine in zoneTabLines) 132 | { 133 | // Ignore comments 134 | if (![zoneTabLine hasPrefix:@"#"]) 135 | { 136 | NSArray *zoneTabLineColumns; 137 | 138 | // Split in columns 139 | if ((zoneTabLineColumns = [zoneTabLine componentsSeparatedByString:tab]) != nil) 140 | { 141 | NSUInteger columnCount = [zoneTabLineColumns count]; 142 | 143 | // Minimum number of columns 144 | if (columnCount >= 3) 145 | { 146 | BOOL addRecord = YES; 147 | NSString *countryCode = zoneTabLineColumns[0]; // f.ex. DE 148 | NSString *coordinates = zoneTabLineColumns[1]; // f.ex. +5230+01322 149 | NSString *timeZoneName = zoneTabLineColumns[2]; // f.ex. Europe/Berlin 150 | 151 | if (onlyZoneName != nil) 152 | { 153 | addRecord = [timeZoneName isEqual:onlyZoneName]; 154 | } 155 | 156 | if (addRecord) 157 | { 158 | // Add record 159 | [recordsByTimeZone setObject:@{ 160 | kISTZCLCountryCodeKey : countryCode, 161 | kISTZCLCoordinatesKey : coordinates, 162 | kISTZCLTimeZoneNameKey : timeZoneName 163 | } forKey:timeZoneName]; 164 | 165 | if (onlyZoneName != nil) 166 | { 167 | // If only this time zone's record was requested, we can skip parsing the rest 168 | break; 169 | } 170 | } 171 | } 172 | } 173 | } 174 | } 175 | 176 | [zoneTabContents release]; 177 | } 178 | 179 | return (recordsByTimeZone); 180 | } 181 | 182 | + (CLLocation *)IS_locationFromCoordinatesString:(NSString *)coordinateString 183 | { 184 | NSUInteger coordinatesLength = [coordinateString length]; 185 | 186 | // Extract coordinates 187 | if (coordinatesLength > 1) 188 | { 189 | NSRange signRange; 190 | 191 | signRange = [coordinateString rangeOfString:@"+" options:0 range:NSMakeRange(1, coordinatesLength-1)]; 192 | 193 | if (signRange.location == NSNotFound) 194 | { 195 | signRange = [coordinateString rangeOfString:@"-" options:0 range:NSMakeRange(1, coordinatesLength-1)]; 196 | } 197 | 198 | if (signRange.location != NSNotFound) 199 | { 200 | double longitude, latitude; 201 | 202 | // Convert from ISO6709 to degrees 203 | longitude = [self IS_degreesFromISO6709String:[coordinateString substringToIndex:signRange.location]]; 204 | latitude = [self IS_degreesFromISO6709String:[coordinateString substringFromIndex:signRange.location]]; 205 | 206 | // Create a CLLocation from this 207 | return ([[[CLLocation alloc] initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude] autorelease]); 208 | } 209 | } 210 | 211 | return (nil); 212 | } 213 | 214 | + (NSDictionary *)IS_timeZoneDictForTimeZoneName:(NSString *)timeZoneName 215 | { 216 | if (timeZoneName != nil) 217 | { 218 | NSDictionary *recordsByTimeZoneDict = [[self class] IS_recordsByTimeZoneFromZoneTabFile:nil onlyZoneName:timeZoneName]; 219 | 220 | if ((timeZoneName!=nil) && (recordsByTimeZoneDict!=nil)) 221 | { 222 | return ([recordsByTimeZoneDict objectForKey:timeZoneName]); 223 | } 224 | } 225 | 226 | return (nil); 227 | } 228 | 229 | #pragma mark - API 230 | + (void)preloadTimeZoneLocationTable 231 | { 232 | @synchronized(self) 233 | { 234 | if (sISTimeZoneLocationDict==nil) 235 | { 236 | sISTimeZoneLocationDict = [[self IS_recordsByTimeZoneFromZoneTabFile:nil onlyZoneName:nil] retain]; 237 | } 238 | } 239 | } 240 | 241 | - (NSString *)ISO3166CountryCode 242 | { 243 | NSString *returnCountryCode = nil; 244 | NSDictionary *timeZoneRecord = nil; 245 | NSString *tzName = self.name; 246 | 247 | if (tzName == nil) { return(nil); } 248 | 249 | @synchronized(self) 250 | { 251 | if (sISTimeZoneCountryCodeCacheDict == nil) 252 | { 253 | sISTimeZoneCountryCodeCacheDict = [[NSMutableDictionary alloc] init]; 254 | } 255 | else 256 | { 257 | if ((returnCountryCode = [sISTimeZoneCountryCodeCacheDict objectForKey:tzName]) != nil) 258 | { 259 | return (returnCountryCode); 260 | } 261 | } 262 | } 263 | 264 | if ((timeZoneRecord = [[self class] IS_timeZoneDictForTimeZoneName:self.name]) != nil) 265 | { 266 | if ((returnCountryCode = [timeZoneRecord objectForKey:kISTZCLCountryCodeKey]) != nil) 267 | { 268 | @synchronized(self) 269 | { 270 | [sISTimeZoneCountryCodeCacheDict setObject:returnCountryCode forKey:tzName]; 271 | } 272 | } 273 | } 274 | 275 | return (returnCountryCode); 276 | } 277 | 278 | - (CLLocation *)approximateLocation 279 | { 280 | CLLocation *returnLocation = nil; 281 | NSDictionary *timeZoneRecord = nil; 282 | NSString *tzName = self.name; 283 | 284 | if (tzName == nil) { return(nil); } 285 | 286 | @synchronized(self) 287 | { 288 | if (sISTimeZoneLocationCacheDict == nil) 289 | { 290 | sISTimeZoneLocationCacheDict = [[NSMutableDictionary alloc] init]; 291 | } 292 | else 293 | { 294 | if ((returnLocation = [sISTimeZoneLocationCacheDict objectForKey:tzName]) != nil) 295 | { 296 | return (returnLocation); 297 | } 298 | } 299 | } 300 | 301 | if ((timeZoneRecord = [[self class] IS_timeZoneDictForTimeZoneName:tzName]) != nil) 302 | { 303 | if ((returnLocation = [[self class] IS_locationFromCoordinatesString:[timeZoneRecord objectForKey:kISTZCLCoordinatesKey]]) != nil) 304 | { 305 | @synchronized(self) 306 | { 307 | [sISTimeZoneLocationCacheDict setObject:returnLocation forKey:tzName]; 308 | } 309 | } 310 | } 311 | 312 | return (returnLocation); 313 | } 314 | 315 | @end 316 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NSTimeZone+ISCLLocation 2 | Category for NSTimeZone that provides Core Location CLLocations and ISO 3166 country codes for named time zones (e.g. "Europe/Berlin") from the IANA Time Zone Database. Provides location data too general to invade the privacy of the user, but sufficient to calculate f.ex. sunrise and sunset times. Includes the database, so it works without GPS and network connection. Works with iOS and OS X. 3 | 4 | *by [@felix_schwarz](https://twitter.com/felix_schwarz/)* 5 | 6 | ## Inspiration 7 | I looked for a way to support day and night modes in an upcoming iOS app I'm working on. It is an integral part of the user experience, so ideally, it should "just work" - without requiring any steps on the part of the user. 8 | 9 | Core Location would prompt and require users to share their precise location (whereas an approximation would do). It also would need access to GPS and/or the Internet. That's a lot of moving parts. 10 | 11 | Since the time zone set on most devices takes the form of "Continent/City" (f.ex. "Europe/Berlin") *and* is updated by iOS by default, it immediately felt like a better choice. However, NSTimeZone does not provide any location information out of the box. 12 | 13 | This category fills that gap, adding CLLocation and ISO 3166 country code accessors to NSTimeZone. 14 | 15 | ## Adding NSTimeZone+ISCLLocation to your project 16 | * Add NSTimeZone+ISCLLocation.m and NSTimeZone+ISCLLocation.h to your project's sources 17 | * Add zone.tab to your project's resources so that they're included in the same bundle as the object code for NSTimeZone+ISCLLocation.m 18 | * Add the CoreLocation.framework to your project (necessary to use the CLLocation class) 19 | 20 | ## Usage 21 | 22 | ### Get approximate location as CLLocation 23 | 24 | ```objc 25 | #import "NSTimeZone+ISCLLocation.h" 26 | 27 | … 28 | 29 | NSTimeZone *timeZone = [NSTimeZone localTimeZone]; 30 | CLLocation *location; 31 | 32 | if ((location = [timeZone approximateLocation]) != nil) 33 | { 34 | // Location found in database 35 | NSLog(@"Location of this timezone: %@", location); 36 | } 37 | else 38 | { 39 | // No location found in database. 40 | NSLog(@"No location found for timezone %@", timeZone.name); 41 | } 42 | ``` 43 | 44 | ### Get the ISO 3166 country code 45 | 46 | ```objc 47 | #import "NSTimeZone+ISCLLocation.h" 48 | 49 | … 50 | 51 | NSTimeZone *timeZone = [NSTimeZone localTimeZone]; 52 | NSString *countryCode; 53 | 54 | if ((countryCode = [timeZone ISO3166CountryCode]) != nil) 55 | { 56 | // Location found in database 57 | NSLog(@"Country of this timezone: %@", countryCode); 58 | } 59 | else 60 | { 61 | // No location found in database. 62 | NSLog(@"No country found for timezone %@", timeZone.name); 63 | } 64 | ``` 65 | 66 | ### Caching 67 | 68 | * Calls to -[NSTimeZone approximateLocation] and -[NSTimeZone ISO3166CountryCode] will cache results and reuse them on subsequent calls. 69 | * If no previous result can be found in the cache, the entire zone.tab file is loaded and parsed. 70 | * To avoid parsing the zone.tab file more than once, call +[NSTimeZone preloadTimeZoneLocationTable] before using the other methods. That will preload the time zone database and keep it in memory. 71 | 72 | ### Sunrise and sunset 73 | 74 | Pair it with [CLLocation-SunriseSunset](https://github.com/BigZaphod/CLLocation-SunriseSunset) to calculate sunrise and sunset times. 75 | 76 | ## Data 77 | 78 | NSTimeZone+ISCLLocation uses data from the [IANA Time Zone Database](https://www.iana.org/time-zones). 79 | 80 | ## License 81 | 82 | NSTimeZone+ISCLLocation is MIT licensed. 83 | -------------------------------------------------------------------------------- /zone.tab: -------------------------------------------------------------------------------- 1 | # TZ zone descriptions 2 | # 3 | # This file is in the public domain, so clarified as of 4 | # 2009-05-17 by Arthur David Olson. 5 | # 6 | # From Paul Eggert (2013-08-14): 7 | # 8 | # This file contains a table where each row stands for an area that is 9 | # the intersection of a region identified by a country code and of a 10 | # zone where civil clocks have agreed since 1970. The columns of the 11 | # table are as follows: 12 | # 13 | # 1. ISO 3166 2-character country code. See the file 'iso3166.tab'. 14 | # 2. Latitude and longitude of the area's principal location 15 | # in ISO 6709 sign-degrees-minutes-seconds format, 16 | # either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, 17 | # first latitude (+ is north), then longitude (+ is east). 18 | # 3. Zone name used in value of TZ environment variable. 19 | # Please see the 'Theory' file for how zone names are chosen. 20 | # If multiple zones overlap a country, each has a row in the 21 | # table, with column 1 being duplicated. 22 | # 4. Comments; present if and only if the country has multiple rows. 23 | # 24 | # Columns are separated by a single tab. 25 | # The table is sorted first by country, then an order within the country that 26 | # (1) makes some geographical sense, and 27 | # (2) puts the most populous areas first, where that does not contradict (1). 28 | # 29 | # Lines beginning with '#' are comments. 30 | # 31 | # This table is intended as an aid for users, to help them select time 32 | # zone data appropriate for their practical needs. It is not intended 33 | # to take or endorse any position on legal or territorial claims. 34 | # 35 | #country- 36 | #code coordinates TZ comments 37 | AD +4230+00131 Europe/Andorra 38 | AE +2518+05518 Asia/Dubai 39 | AF +3431+06912 Asia/Kabul 40 | AG +1703-06148 America/Antigua 41 | AI +1812-06304 America/Anguilla 42 | AL +4120+01950 Europe/Tirane 43 | AM +4011+04430 Asia/Yerevan 44 | AO -0848+01314 Africa/Luanda 45 | AQ -7750+16636 Antarctica/McMurdo McMurdo, South Pole, Scott (New Zealand time) 46 | AQ -6734-06808 Antarctica/Rothera Rothera Station, Adelaide Island 47 | AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island 48 | AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay 49 | AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills 50 | AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula 51 | AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok 52 | AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie 53 | AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I 54 | AQ -720041+0023206 Antarctica/Troll Troll Station, Queen Maud Land 55 | AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) 56 | AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) 57 | AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) 58 | AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) 59 | AR -2649-06513 America/Argentina/Tucuman Tucuman (TM) 60 | AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) 61 | AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) 62 | AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) 63 | AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) 64 | AR -3319-06621 America/Argentina/San_Luis San Luis (SL) 65 | AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) 66 | AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) 67 | AS -1416-17042 Pacific/Pago_Pago 68 | AT +4813+01620 Europe/Vienna 69 | AU -3133+15905 Australia/Lord_Howe Lord Howe Island 70 | AU -5430+15857 Antarctica/Macquarie Macquarie Island 71 | AU -4253+14719 Australia/Hobart Tasmania - most locations 72 | AU -3956+14352 Australia/Currie Tasmania - King Island 73 | AU -3749+14458 Australia/Melbourne Victoria 74 | AU -3352+15113 Australia/Sydney New South Wales - most locations 75 | AU -3157+14127 Australia/Broken_Hill New South Wales - Yancowinna 76 | AU -2728+15302 Australia/Brisbane Queensland - most locations 77 | AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands 78 | AU -3455+13835 Australia/Adelaide South Australia 79 | AU -1228+13050 Australia/Darwin Northern Territory 80 | AU -3157+11551 Australia/Perth Western Australia - most locations 81 | AU -3143+12852 Australia/Eucla Western Australia - Eucla area 82 | AW +1230-06958 America/Aruba 83 | AX +6006+01957 Europe/Mariehamn 84 | AZ +4023+04951 Asia/Baku 85 | BA +4352+01825 Europe/Sarajevo 86 | BB +1306-05937 America/Barbados 87 | BD +2343+09025 Asia/Dhaka 88 | BE +5050+00420 Europe/Brussels 89 | BF +1222-00131 Africa/Ouagadougou 90 | BG +4241+02319 Europe/Sofia 91 | BH +2623+05035 Asia/Bahrain 92 | BI -0323+02922 Africa/Bujumbura 93 | BJ +0629+00237 Africa/Porto-Novo 94 | BL +1753-06251 America/St_Barthelemy 95 | BM +3217-06446 Atlantic/Bermuda 96 | BN +0456+11455 Asia/Brunei 97 | BO -1630-06809 America/La_Paz 98 | BQ +120903-0681636 America/Kralendijk 99 | BR -0351-03225 America/Noronha Atlantic islands 100 | BR -0127-04829 America/Belem Amapa, E Para 101 | BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB) 102 | BR -0803-03454 America/Recife Pernambuco 103 | BR -0712-04812 America/Araguaina Tocantins 104 | BR -0940-03543 America/Maceio Alagoas, Sergipe 105 | BR -1259-03831 America/Bahia Bahia 106 | BR -2332-04637 America/Sao_Paulo S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS) 107 | BR -2027-05437 America/Campo_Grande Mato Grosso do Sul 108 | BR -1535-05605 America/Cuiaba Mato Grosso 109 | BR -0226-05452 America/Santarem W Para 110 | BR -0846-06354 America/Porto_Velho Rondonia 111 | BR +0249-06040 America/Boa_Vista Roraima 112 | BR -0308-06001 America/Manaus E Amazonas 113 | BR -0640-06952 America/Eirunepe W Amazonas 114 | BR -0958-06748 America/Rio_Branco Acre 115 | BS +2505-07721 America/Nassau 116 | BT +2728+08939 Asia/Thimphu 117 | BW -2439+02555 Africa/Gaborone 118 | BY +5354+02734 Europe/Minsk 119 | BZ +1730-08812 America/Belize 120 | CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador 121 | CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI 122 | CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 123 | CA +4606-06447 America/Moncton Atlantic Time - New Brunswick 124 | CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations 125 | CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore 126 | CA +4339-07923 America/Toronto Eastern Time - Ontario & Quebec - most locations 127 | CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 128 | CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario 129 | CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations 130 | CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut 131 | CA +744144-0944945 America/Resolute Central Standard Time - Resolute, Nunavut 132 | CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut 133 | CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut 134 | CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario 135 | CA +4843-09434 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario 136 | CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations 137 | CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest 138 | CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan 139 | CA +690650-1050310 America/Cambridge_Bay Mountain Time - west Nunavut 140 | CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories 141 | CA +682059-1334300 America/Inuvik Mountain Time - west Northwest Territories 142 | CA +4906-11631 America/Creston Mountain Standard Time - Creston, British Columbia 143 | CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia 144 | CA +4916-12307 America/Vancouver Pacific Time - west British Columbia 145 | CA +6043-13503 America/Whitehorse Pacific Time - south Yukon 146 | CA +6404-13925 America/Dawson Pacific Time - north Yukon 147 | CC -1210+09655 Indian/Cocos 148 | CD -0418+01518 Africa/Kinshasa west Dem. Rep. of Congo 149 | CD -1140+02728 Africa/Lubumbashi east Dem. Rep. of Congo 150 | CF +0422+01835 Africa/Bangui 151 | CG -0416+01517 Africa/Brazzaville 152 | CH +4723+00832 Europe/Zurich 153 | CI +0519-00402 Africa/Abidjan 154 | CK -2114-15946 Pacific/Rarotonga 155 | CL -3327-07040 America/Santiago most locations 156 | CL -2709-10926 Pacific/Easter Easter Island & Sala y Gomez 157 | CM +0403+00942 Africa/Douala 158 | CN +3114+12128 Asia/Shanghai east China - Beijing, Guangdong, Shanghai, etc. 159 | CN +4545+12641 Asia/Harbin Heilongjiang (except Mohe), Jilin 160 | CN +2934+10635 Asia/Chongqing central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc. 161 | CN +4348+08735 Asia/Urumqi most of Tibet & Xinjiang 162 | CN +3929+07559 Asia/Kashgar west Tibet & Xinjiang 163 | CO +0436-07405 America/Bogota 164 | CR +0956-08405 America/Costa_Rica 165 | CU +2308-08222 America/Havana 166 | CV +1455-02331 Atlantic/Cape_Verde 167 | CW +1211-06900 America/Curacao 168 | CX -1025+10543 Indian/Christmas 169 | CY +3510+03322 Asia/Nicosia 170 | CZ +5005+01426 Europe/Prague 171 | DE +5230+01322 Europe/Berlin most locations 172 | DE +4742+00841 Europe/Busingen Busingen 173 | DJ +1136+04309 Africa/Djibouti 174 | DK +5540+01235 Europe/Copenhagen 175 | DM +1518-06124 America/Dominica 176 | DO +1828-06954 America/Santo_Domingo 177 | DZ +3647+00303 Africa/Algiers 178 | EC -0210-07950 America/Guayaquil mainland 179 | EC -0054-08936 Pacific/Galapagos Galapagos Islands 180 | EE +5925+02445 Europe/Tallinn 181 | EG +3003+03115 Africa/Cairo 182 | EH +2709-01312 Africa/El_Aaiun 183 | ER +1520+03853 Africa/Asmara 184 | ES +4024-00341 Europe/Madrid mainland 185 | ES +3553-00519 Africa/Ceuta Ceuta & Melilla 186 | ES +2806-01524 Atlantic/Canary Canary Islands 187 | ET +0902+03842 Africa/Addis_Ababa 188 | FI +6010+02458 Europe/Helsinki 189 | FJ -1808+17825 Pacific/Fiji 190 | FK -5142-05751 Atlantic/Stanley 191 | FM +0725+15147 Pacific/Chuuk Chuuk (Truk) and Yap 192 | FM +0658+15813 Pacific/Pohnpei Pohnpei (Ponape) 193 | FM +0519+16259 Pacific/Kosrae Kosrae 194 | FO +6201-00646 Atlantic/Faroe 195 | FR +4852+00220 Europe/Paris 196 | GA +0023+00927 Africa/Libreville 197 | GB +513030-0000731 Europe/London 198 | GD +1203-06145 America/Grenada 199 | GE +4143+04449 Asia/Tbilisi 200 | GF +0456-05220 America/Cayenne 201 | GG +4927-00232 Europe/Guernsey 202 | GH +0533-00013 Africa/Accra 203 | GI +3608-00521 Europe/Gibraltar 204 | GL +6411-05144 America/Godthab most locations 205 | GL +7646-01840 America/Danmarkshavn east coast, north of Scoresbysund 206 | GL +7029-02158 America/Scoresbysund Scoresbysund / Ittoqqortoormiit 207 | GL +7634-06847 America/Thule Thule / Pituffik 208 | GM +1328-01639 Africa/Banjul 209 | GN +0931-01343 Africa/Conakry 210 | GP +1614-06132 America/Guadeloupe 211 | GQ +0345+00847 Africa/Malabo 212 | GR +3758+02343 Europe/Athens 213 | GS -5416-03632 Atlantic/South_Georgia 214 | GT +1438-09031 America/Guatemala 215 | GU +1328+14445 Pacific/Guam 216 | GW +1151-01535 Africa/Bissau 217 | GY +0648-05810 America/Guyana 218 | HK +2217+11409 Asia/Hong_Kong 219 | HN +1406-08713 America/Tegucigalpa 220 | HR +4548+01558 Europe/Zagreb 221 | HT +1832-07220 America/Port-au-Prince 222 | HU +4730+01905 Europe/Budapest 223 | ID -0610+10648 Asia/Jakarta Java & Sumatra 224 | ID -0002+10920 Asia/Pontianak west & central Borneo 225 | ID -0507+11924 Asia/Makassar east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor 226 | ID -0232+14042 Asia/Jayapura west New Guinea (Irian Jaya) & Malukus (Moluccas) 227 | IE +5320-00615 Europe/Dublin 228 | IL +314650+0351326 Asia/Jerusalem 229 | IM +5409-00428 Europe/Isle_of_Man 230 | IN +2232+08822 Asia/Kolkata 231 | IO -0720+07225 Indian/Chagos 232 | IQ +3321+04425 Asia/Baghdad 233 | IR +3540+05126 Asia/Tehran 234 | IS +6409-02151 Atlantic/Reykjavik 235 | IT +4154+01229 Europe/Rome 236 | JE +4912-00207 Europe/Jersey 237 | JM +175805-0764736 America/Jamaica 238 | JO +3157+03556 Asia/Amman 239 | JP +353916+1394441 Asia/Tokyo 240 | KE -0117+03649 Africa/Nairobi 241 | KG +4254+07436 Asia/Bishkek 242 | KH +1133+10455 Asia/Phnom_Penh 243 | KI +0125+17300 Pacific/Tarawa Gilbert Islands 244 | KI -0308-17105 Pacific/Enderbury Phoenix Islands 245 | KI +0152-15720 Pacific/Kiritimati Line Islands 246 | KM -1141+04316 Indian/Comoro 247 | KN +1718-06243 America/St_Kitts 248 | KP +3901+12545 Asia/Pyongyang 249 | KR +3733+12658 Asia/Seoul 250 | KW +2920+04759 Asia/Kuwait 251 | KY +1918-08123 America/Cayman 252 | KZ +4315+07657 Asia/Almaty most locations 253 | KZ +4448+06528 Asia/Qyzylorda Qyzylorda (Kyzylorda, Kzyl-Orda) 254 | KZ +5017+05710 Asia/Aqtobe Aqtobe (Aktobe) 255 | KZ +4431+05016 Asia/Aqtau Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau) 256 | KZ +5113+05121 Asia/Oral West Kazakhstan 257 | LA +1758+10236 Asia/Vientiane 258 | LB +3353+03530 Asia/Beirut 259 | LC +1401-06100 America/St_Lucia 260 | LI +4709+00931 Europe/Vaduz 261 | LK +0656+07951 Asia/Colombo 262 | LR +0618-01047 Africa/Monrovia 263 | LS -2928+02730 Africa/Maseru 264 | LT +5441+02519 Europe/Vilnius 265 | LU +4936+00609 Europe/Luxembourg 266 | LV +5657+02406 Europe/Riga 267 | LY +3254+01311 Africa/Tripoli 268 | MA +3339-00735 Africa/Casablanca 269 | MC +4342+00723 Europe/Monaco 270 | MD +4700+02850 Europe/Chisinau 271 | ME +4226+01916 Europe/Podgorica 272 | MF +1804-06305 America/Marigot 273 | MG -1855+04731 Indian/Antananarivo 274 | MH +0709+17112 Pacific/Majuro most locations 275 | MH +0905+16720 Pacific/Kwajalein Kwajalein 276 | MK +4159+02126 Europe/Skopje 277 | ML +1239-00800 Africa/Bamako 278 | MM +1647+09610 Asia/Rangoon 279 | MN +4755+10653 Asia/Ulaanbaatar most locations 280 | MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan 281 | MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar 282 | MO +2214+11335 Asia/Macau 283 | MP +1512+14545 Pacific/Saipan 284 | MQ +1436-06105 America/Martinique 285 | MR +1806-01557 Africa/Nouakchott 286 | MS +1643-06213 America/Montserrat 287 | MT +3554+01431 Europe/Malta 288 | MU -2010+05730 Indian/Mauritius 289 | MV +0410+07330 Indian/Maldives 290 | MW -1547+03500 Africa/Blantyre 291 | MX +1924-09909 America/Mexico_City Central Time - most locations 292 | MX +2105-08646 America/Cancun Central Time - Quintana Roo 293 | MX +2058-08937 America/Merida Central Time - Campeche, Yucatan 294 | MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border 295 | MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border 296 | MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa 297 | MX +2838-10605 America/Chihuahua Mexican Mountain Time - Chihuahua away from US border 298 | MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border 299 | MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora 300 | MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border 301 | MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border 302 | MX +2048-10515 America/Bahia_Banderas Mexican Central Time - Bahia de Banderas 303 | MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia 304 | MY +0133+11020 Asia/Kuching Sabah & Sarawak 305 | MZ -2558+03235 Africa/Maputo 306 | NA -2234+01706 Africa/Windhoek 307 | NC -2216+16627 Pacific/Noumea 308 | NE +1331+00207 Africa/Niamey 309 | NF -2903+16758 Pacific/Norfolk 310 | NG +0627+00324 Africa/Lagos 311 | NI +1209-08617 America/Managua 312 | NL +5222+00454 Europe/Amsterdam 313 | NO +5955+01045 Europe/Oslo 314 | NP +2743+08519 Asia/Kathmandu 315 | NR -0031+16655 Pacific/Nauru 316 | NU -1901-16955 Pacific/Niue 317 | NZ -3652+17446 Pacific/Auckland most locations 318 | NZ -4357-17633 Pacific/Chatham Chatham Islands 319 | OM +2336+05835 Asia/Muscat 320 | PA +0858-07932 America/Panama 321 | PE -1203-07703 America/Lima 322 | PF -1732-14934 Pacific/Tahiti Society Islands 323 | PF -0900-13930 Pacific/Marquesas Marquesas Islands 324 | PF -2308-13457 Pacific/Gambier Gambier Islands 325 | PG -0930+14710 Pacific/Port_Moresby 326 | PH +1435+12100 Asia/Manila 327 | PK +2452+06703 Asia/Karachi 328 | PL +5215+02100 Europe/Warsaw 329 | PM +4703-05620 America/Miquelon 330 | PN -2504-13005 Pacific/Pitcairn 331 | PR +182806-0660622 America/Puerto_Rico 332 | PS +3130+03428 Asia/Gaza Gaza Strip 333 | PS +313200+0350542 Asia/Hebron West Bank 334 | PT +3843-00908 Europe/Lisbon mainland 335 | PT +3238-01654 Atlantic/Madeira Madeira Islands 336 | PT +3744-02540 Atlantic/Azores Azores 337 | PW +0720+13429 Pacific/Palau 338 | PY -2516-05740 America/Asuncion 339 | QA +2517+05132 Asia/Qatar 340 | RE -2052+05528 Indian/Reunion 341 | RO +4426+02606 Europe/Bucharest 342 | RS +4450+02030 Europe/Belgrade 343 | RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad 344 | RU +5545+03735 Europe/Moscow Moscow+00 - west Russia 345 | RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea 346 | RU +5312+05009 Europe/Samara Moscow+00 - Samara, Udmurtia 347 | RU +4457+03406 Europe/Simferopol Moscow+00 - Crimea 348 | RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals 349 | RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia 350 | RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk 351 | RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk 352 | RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River 353 | RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal 354 | RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River 355 | RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky 356 | RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River 357 | RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island 358 | RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky 359 | RU +5934+15048 Asia/Magadan Moscow+08 - Magadan 360 | RU +5301+15839 Asia/Kamchatka Moscow+08 - Kamchatka 361 | RU +6445+17729 Asia/Anadyr Moscow+08 - Bering Sea 362 | RW -0157+03004 Africa/Kigali 363 | SA +2438+04643 Asia/Riyadh 364 | SB -0932+16012 Pacific/Guadalcanal 365 | SC -0440+05528 Indian/Mahe 366 | SD +1536+03232 Africa/Khartoum 367 | SE +5920+01803 Europe/Stockholm 368 | SG +0117+10351 Asia/Singapore 369 | SH -1555-00542 Atlantic/St_Helena 370 | SI +4603+01431 Europe/Ljubljana 371 | SJ +7800+01600 Arctic/Longyearbyen 372 | SK +4809+01707 Europe/Bratislava 373 | SL +0830-01315 Africa/Freetown 374 | SM +4355+01228 Europe/San_Marino 375 | SN +1440-01726 Africa/Dakar 376 | SO +0204+04522 Africa/Mogadishu 377 | SR +0550-05510 America/Paramaribo 378 | SS +0451+03136 Africa/Juba 379 | ST +0020+00644 Africa/Sao_Tome 380 | SV +1342-08912 America/El_Salvador 381 | SX +180305-0630250 America/Lower_Princes 382 | SY +3330+03618 Asia/Damascus 383 | SZ -2618+03106 Africa/Mbabane 384 | TC +2128-07108 America/Grand_Turk 385 | TD +1207+01503 Africa/Ndjamena 386 | TF -492110+0701303 Indian/Kerguelen 387 | TG +0608+00113 Africa/Lome 388 | TH +1345+10031 Asia/Bangkok 389 | TJ +3835+06848 Asia/Dushanbe 390 | TK -0922-17114 Pacific/Fakaofo 391 | TL -0833+12535 Asia/Dili 392 | TM +3757+05823 Asia/Ashgabat 393 | TN +3648+01011 Africa/Tunis 394 | TO -2110-17510 Pacific/Tongatapu 395 | TR +4101+02858 Europe/Istanbul 396 | TT +1039-06131 America/Port_of_Spain 397 | TV -0831+17913 Pacific/Funafuti 398 | TW +2503+12130 Asia/Taipei 399 | TZ -0648+03917 Africa/Dar_es_Salaam 400 | UA +5026+03031 Europe/Kiev most locations 401 | UA +4837+02218 Europe/Uzhgorod Ruthenia 402 | UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk 403 | UG +0019+03225 Africa/Kampala 404 | UM +1645-16931 Pacific/Johnston Johnston Atoll 405 | UM +2813-17722 Pacific/Midway Midway Islands 406 | UM +1917+16637 Pacific/Wake Wake Island 407 | US +404251-0740023 America/New_York Eastern Time 408 | US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations 409 | US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisville area 410 | US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County 411 | US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations 412 | US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties 413 | US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County 414 | US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County 415 | US +382931-0871643 America/Indiana/Petersburg Eastern Time - Indiana - Pike County 416 | US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County 417 | US +415100-0873900 America/Chicago Central Time 418 | US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County 419 | US +411745-0863730 America/Indiana/Knox Central Time - Indiana - Starke County 420 | US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties 421 | US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County 422 | US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) 423 | US +471551-1014640 America/North_Dakota/Beulah Central Time - North Dakota - Mercer County 424 | US +394421-1045903 America/Denver Mountain Time 425 | US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon 426 | US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona (except Navajo) 427 | US +340308-1181434 America/Los_Angeles Pacific Time 428 | US +611305-1495401 America/Anchorage Alaska Time 429 | US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle 430 | US +571035-1351807 America/Sitka Alaska Time - southeast Alaska panhandle 431 | US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck 432 | US +643004-1652423 America/Nome Alaska Time - west Alaska 433 | US +515248-1763929 America/Adak Aleutian Islands 434 | US +550737-1313435 America/Metlakatla Metlakatla Time - Annette Island 435 | US +211825-1575130 Pacific/Honolulu Hawaii 436 | UY -3453-05611 America/Montevideo 437 | UZ +3940+06648 Asia/Samarkand west Uzbekistan 438 | UZ +4120+06918 Asia/Tashkent east Uzbekistan 439 | VA +415408+0122711 Europe/Vatican 440 | VC +1309-06114 America/St_Vincent 441 | VE +1030-06656 America/Caracas 442 | VG +1827-06437 America/Tortola 443 | VI +1821-06456 America/St_Thomas 444 | VN +1045+10640 Asia/Ho_Chi_Minh 445 | VU -1740+16825 Pacific/Efate 446 | WF -1318-17610 Pacific/Wallis 447 | WS -1350-17144 Pacific/Apia 448 | YE +1245+04512 Asia/Aden 449 | YT -1247+04514 Indian/Mayotte 450 | ZA -2615+02800 Africa/Johannesburg 451 | ZM -1525+02817 Africa/Lusaka 452 | ZW -1750+03103 Africa/Harare 453 | --------------------------------------------------------------------------------