日期选择器和列表选择器(多个时区),用于创建计划日期字符串

时间:2017-06-07 17:09:09

标签: ios objective-c

在此项目的UI端,有一个日期选择器和列表选择器,旨在允许用户选择特定时区的未来时间和日期,以安排通过语音,短信,电子邮件等广播警报。不幸的是,GMT偏移量没有正确调整。例如,2017年6月7日17:33在德国柏林(GMT + 0200)预定的警报实际上是柏林时间02:30的第二天。

  

2017-06-08 00:33:00 +0200

1。谁会知道什么可能导致这种差异,以及如何     为所有时区纠正?

2。调整所有预定的步骤是必要的     中部夏令时的时间?

Screenshot of New Alert View Controller

在NewAlertTableViewController.m中,此函数更新日期选择器标签:

- (void) updateDateLabel {
    NSDate *now                  = [NSDate date];
    NSDate *scheduledDate        = self.datePicker.date;
    if ([scheduledDate isToday] && scheduledDate.hour <= now.hour && scheduledDate.minute <= now.minute) {
        self.dateLabel.text      = NSLocalizedString(@"Now", @"label for time an alert is scheduled to be sent");
        self.sendButton.title    = NSLocalizedString(@"Send Alert", @"button label for sending an alert");
        self.alert.sendNow       = YES;
    } else if ([scheduledDate isToday]) {
        self.dateLabel.text      = [NSString stringWithFormat: NSLocalizedString(@"Today, %@", @"label for time an alert is scheduled to be sent"), [scheduledDate stringWithDateStyle: NSDateFormatterNoStyle                                                                                                                                                                       timeStyle: NSDateFormatterShortStyle]];
        self.sendButton.title    = NSLocalizedString(@"Save Alert", @"button label for saving an alert");
        self.alert.sendNow       = NO;
    } else {
        self.dateLabel.text      = [scheduledDate stringWithDateStyle: NSDateFormatterShortStyle
                                                            timeStyle: NSDateFormatterShortStyle];
        self.sendButton.title    = NSLocalizedString(@"Save Alert", @"button label for saving an alert");
        self.alert.sendNow       = NO;
    }
    self.alert.scheduledDate     = scheduledDate;
    DDLogInfo(@"Date Picker: %@", scheduledDate);
}

同样在NewAlertTableViewController.m中,我们有这个委托来处理时区选择器视图:

- (void) pickerView: (UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent: (NSInteger)component {
    NSString *timeZone;
    NSString *timeZoneCity;
    NSDateFormatter *systemTimeZoneFormatter = [NSDateFormatter new];
    systemTimeZoneFormatter.timeZone         = [NSTimeZone localTimeZone];
    systemTimeZoneFormatter.dateFormat       = @"Z";
    NSString *systemTimeZoneOffset           = [systemTimeZoneFormatter stringFromDate: [NSDate date]];
    switch (row) {
        case 0:
            timeZone     = (@"GMT%@", systemTimeZoneOffset);
            timeZoneCity = @"Device Default";
            break;
        case 1:
            timeZone     = @"GMT+02:00";
            timeZoneCity = @"Berlin";
            break;
        case 2:
            timeZone     = @"GMT+01:00";
            timeZoneCity = @"London";
            break;
        case 3:
            timeZone     = @"GMT-04:00";
            timeZoneCity = @"New York";
            break;
        case 4:
            timeZone     = @"GMT-05:00";
            timeZoneCity = @"Chicago";
            break;
        case 5:
            timeZone     = @"GMT-06:00";
            timeZoneCity = @"Denver";
            break;
        case 6:
            timeZone     = @"GMT-07:00";
            timeZoneCity = @"Los Angeles";
            break;
        case 7:
            timeZone     = @"GMT-08:00";
            timeZoneCity = @"Anchorage";
            break;
        case 8:
            timeZone     = @"GMT-10:00";
            timeZoneCity = @"Honolulu";
            break;
        default:
            break;
    }
    [self updateTimeZone: timeZone];
    [[NSUserDefaults standardUserDefaults] setObject: timeZone forKey: @"timeZonePreference"];
    DDLogInfo(@"Time Zone Picker: %@, %@", timeZone, timeZoneCity);
    _timeZoneLabel.text = timeZoneCity;
}

在NewAlertTableViewController.m中,此函数再次更新时区:

- (void) updateTimeZone: (id)timeZone {
    self.now                     = [NSDate date];    
    self.calendar                = [[NSCalendar alloc] initWithCalendarIdentifier: NSCalendarIdentifierGregorian];
    [self.calendar setTimeZone: [NSTimeZone timeZoneWithName: timeZone]];
    NSCalendarUnit units         = NSCalendarUnitHour;
    NSDateComponents *components = [self.calendar components: units fromDate: self.now];
    self.hours                   = (int)[components hour];
    self.alert.calendar          = self.calendar;
}

在Alert.m中,我们将此字符串作为参数发送到CreateAlert.aspx端点。 理想情况,我们更喜欢将所有字符串调整为中部夏令时(以匹配我们在德克萨斯州休斯顿的服务器)或至少协调世界时(UTC)。

- (NSString *)scheduledDateString { // This method solely uses the scheduledDate
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat       = @"yyyy-MM-dd HH:mm:ss Z";
    dateFormatter.timeZone         = self.calendar.timeZone;
    NSString *dateString           = [dateFormatter stringFromDate: self.scheduledDate];
    DDLogInfo(@"Scheduled Date: %@", dateString);
    return dateString;
}

2 个答案:

答案 0 :(得分:0)

以下是一些示例代码:

withMargins()

要记住的关键是,无论您是在伦敦,纽约,休斯顿,檀香山,东京,柏林等地,NSDate对象都是相同的。唯一的区别在于它的显示方式。

例如:现在,差不多是下午5点。但等等,当你读到这篇文章时,它可能在下午4点左右 !!!怎么可能?好吧,我现在看// User-selected Time Zone city // using "Europe/Berlin" for this example NSString *timeZoneName = @"Europe/Berlin"; NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:timeZoneName]; // User-selected Date/Time (from the UIDatePicker) NSDate *selDate = _datePicker.date; // Current NSCalendar NSCalendar *calendar = [NSCalendar currentCalendar]; // get all date components from the user-selected Date/Time NSDateComponents *localComponents = [calendar components:-1 fromDate:selDate]; // set the Calendar to use the user-selected Time Zone [calendar setTimeZone: timeZone]; // set the components with the values from localComponents NSDateComponents *timeZoneComponents = [[NSDateComponents alloc] init]; [timeZoneComponents setYear: [localComponents year]]; [timeZoneComponents setMonth: [localComponents month]]; [timeZoneComponents setDay: [localComponents day]]; [timeZoneComponents setHour: [localComponents hour]]; [timeZoneComponents setMinute: [localComponents minute]]; [timeZoneComponents setSecond: [localComponents second]]; // get a NSDate object based on the user-selected Date/Time and Time Zone // Note: if you print the default description of this date, it will show UTC value NSDate *desiredDateTime = [calendar dateFromComponents:timeZoneComponents]; NSLog(@"%@", desiredDateTime); ,我看到&#34; 2017-06-07 20:55:56 + 0000&#34; - 因为那是&#34;绝对&#34;日期/时间。

所以,玩这个代码示例...尝试不同的时区(确保你的名字正确)...看看是否一切都有意义。

如果我做得对(我可能在这里犯了一两个错误)......如果你选择6月16日星期五上午10点在你的约会选择器(不管在哪里)在世界上是),然后运行此代码,最终的[NSDate date];应该打印:

NSLog()

因为UTC比柏林时间早2小时。

答案 1 :(得分:0)

感谢来自 @DonMag 的精明建议,我在家中伸展!现在使用这个新的NewAlertTableViewController.m时区选择器视图委托来获得完美的NSDates:

- (void) pickerView: (UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent: (NSInteger)component {
    NSString *timeZoneName;
    NSString *timeZoneLabel;
    NSDateFormatter *systemTimeZoneFormatter = [NSDateFormatter new];
    systemTimeZoneFormatter.timeZone         = [NSTimeZone localTimeZone];
    systemTimeZoneFormatter.dateFormat       = @"VVVV";
    NSString *systemTimeZoneOffset           = [systemTimeZoneFormatter stringFromDate: [NSDate date]];
    switch (row) {
        case 0:
            timeZoneName  = ("%@", systemTimeZoneOffset);
            timeZoneLabel = @"Device Default";
            break;
        case 1:
            timeZoneName  = @"Europe/Berlin";
            timeZoneLabel = @"Berlin";
            break;
        case 2:
            timeZoneName  = @"Europe/London";
            timeZoneLabel = @"London";
            break;
        case 3:
            timeZoneName  = @"America/New_York";
            timeZoneLabel = @"New York";
            break;
        case 4:
            timeZoneName  = @"America/Chicago";
            timeZoneLabel = @"Chicago";
            break;
        case 5:
            timeZoneName  = @"America/Denver";
            timeZoneLabel = @"Denver";
            break;
        case 6:
            timeZoneName  = @"America/Los_Angeles";
            timeZoneLabel = @"Los Angeles";
            break;
        case 7:
            timeZoneName  = @"America/Anchorage";
            timeZoneLabel = @"Anchorage";
            break;
        case 8:
            timeZoneName  = @"Pacific/Honolulu";
            timeZoneLabel = @"Honolulu";
            break;
        default:
            break;
    }
    [self updateTimeZone: timeZoneName];
    _timeZoneLabel.text                  = timeZoneLabel;
    NSTimeZone *timeZone                 = [NSTimeZone timeZoneWithName: timeZoneName];
    DDLogInfo(@"Time Zone Picker: %@", timeZoneName);
    NSDate *datePickerSelection          = _datePicker.date;
    NSCalendar *calendar                 = [NSCalendar currentCalendar];
    NSDateComponents *localComponents    = [calendar components: -1 fromDate: datePickerSelection];
    [calendar setTimeZone: timeZone];
    NSDateComponents *timeZoneComponents = [[NSDateComponents alloc] init];
    [timeZoneComponents setYear:    [localComponents year]];
    [timeZoneComponents setMonth:   [localComponents month]];
    [timeZoneComponents setDay:     [localComponents day]];
    [timeZoneComponents setHour:    [localComponents hour]];
    [timeZoneComponents setMinute:  [localComponents minute]];
    [timeZoneComponents setSecond:  [localComponents second]];
    _desiredDateTime                     = [calendar dateFromComponents: timeZoneComponents];
    DDLogInfo(@"Desired Date: %@", _desiredDateTime);
}