|
12 | 12 | #import <Foundation/NSDate.h>
|
13 | 13 | #import <Foundation/NSCalendar.h>
|
14 | 14 | #import <limits.h>
|
| 15 | +#import <set> |
| 16 | +#import <string> |
15 | 17 | #include "helper_macros.hpp"
|
16 | 18 |
|
| 19 | +static NSTimeZone * zone_by_name(NSString *zone_name) |
| 20 | +{ |
| 21 | + auto abbreviations = NSTimeZone.abbreviationDictionary; |
| 22 | + auto true_name = [abbreviations valueForKey: zone_name]; |
| 23 | + NSString *name = zone_name; |
| 24 | + if (true_name != nil) { |
| 25 | + name = true_name; |
| 26 | + } |
| 27 | + return [NSTimeZone timeZoneWithName: name]; |
| 28 | +} |
| 29 | + |
17 | 30 | extern "C" {
|
18 | 31 | #include "cdate.h"
|
19 | 32 |
|
|
40 | 53 |
|
41 | 54 | char ** available_zone_ids()
|
42 | 55 | {
|
| 56 | + std::set<std::string> ids; |
43 | 57 | auto zones = NSTimeZone.knownTimeZoneNames;
|
44 |
| - auto abbrevs = NSTimeZone.abbreviationDictionary.allKeys; |
| 58 | + for (NSString * zone in zones) { |
| 59 | + ids.insert(std::string([zone UTF8String])); |
| 60 | + } |
| 61 | + auto abbrevs = NSTimeZone.abbreviationDictionary; |
| 62 | + for (NSString * key in abbrevs) { |
| 63 | + if (ids.count(std::string([abbrevs[key] UTF8String]))) { |
| 64 | + ids.insert(std::string([key UTF8String])); |
| 65 | + } |
| 66 | + } |
45 | 67 | char ** zones_copy = (char **)malloc(
|
46 |
| - sizeof(char *) * (zones.count + abbrevs.count + 1)); |
| 68 | + sizeof(char *) * (ids.size() + 1)); |
47 | 69 | if (zones_copy == nullptr) {
|
48 | 70 | return nullptr;
|
49 | 71 | }
|
50 |
| - zones_copy[zones.count + abbrevs.count] = nullptr; |
51 |
| - unsigned long idx = 0; |
52 |
| - for (unsigned long i = 0; i < zones.count; ++i) { |
53 |
| - idx = i; |
54 |
| - CFIndex bufferSize = zones[i].length + 1; |
55 |
| - char * buffer = (char *)malloc(bufferSize); |
56 |
| - PUSH_BACK_OR_RETURN(zones_copy, idx, buffer); |
57 |
| - strncpy(buffer, zones[i].UTF8String, bufferSize); |
58 |
| - } |
59 |
| - for (unsigned long i = 0; i < abbrevs.count; ++i) { |
60 |
| - idx = zones.count + i; |
61 |
| - CFIndex bufferSize = abbrevs[i].length + 1; |
62 |
| - char * buffer = (char *)malloc(bufferSize); |
63 |
| - PUSH_BACK_OR_RETURN(zones_copy, idx, buffer); |
64 |
| - strncpy(buffer, abbrevs[i].UTF8String, bufferSize); |
| 72 | + zones_copy[ids.size()] = nullptr; |
| 73 | + unsigned long i = 0; |
| 74 | + for (auto it = ids.begin(); it != ids.end(); ++i, ++it) { |
| 75 | + PUSH_BACK_OR_RETURN(zones_copy, i, strdup(it->c_str())); |
65 | 76 | }
|
66 | 77 | return zones_copy;
|
67 | 78 | }
|
68 | 79 |
|
69 | 80 | int offset_at_instant(const char *zone_name, int64_t epoch_sec)
|
70 | 81 | {
|
71 | 82 | auto zone_name_nsstring = [NSString stringWithUTF8String: zone_name];
|
72 |
| - auto zone = [NSTimeZone timeZoneWithName: zone_name_nsstring]; |
| 83 | + auto zone = zone_by_name(zone_name_nsstring); |
73 | 84 | auto date = [NSDate dateWithTimeIntervalSince1970: epoch_sec];
|
74 | 85 | return (int32_t)[zone secondsFromGMTForDate: date];
|
75 | 86 | }
|
76 | 87 |
|
77 | 88 | bool is_known_timezone(const char *zone_name) {
|
78 | 89 | auto zone_name_nsstring = [NSString stringWithUTF8String: zone_name];
|
79 |
| - auto zone = [NSTimeZone timeZoneWithName: zone_name_nsstring]; |
80 |
| - return (zone != nil); |
| 90 | + return (zone_by_name(zone_name_nsstring) != nil); |
81 | 91 | }
|
82 | 92 |
|
83 | 93 | int offset_at_datetime(const char *zone_name, int64_t epoch_sec, int *offset) {
|
84 | 94 | *offset = INT_MAX;
|
85 | 95 | // timezone name
|
86 | 96 | auto zone_name_nsstring = [NSString stringWithUTF8String: zone_name];
|
87 | 97 | // timezone
|
88 |
| - auto zone = [NSTimeZone timeZoneWithName: zone_name_nsstring]; |
| 98 | + auto zone = zone_by_name(zone_name_nsstring); |
89 | 99 | if (zone == nil) { return 0; }
|
90 | 100 | /* a date in an unspecified timezone, defined by the number of seconds since
|
91 | 101 | the start of the epoch in *that* unspecified timezone */
|
|
0 commit comments