iPhone NSCalendar - 为美国以外的用户绘制的日历不正确
在尝试处理别人的代码并进行多次不同的迭代之后,我无法理解我在日历月视图上的日期做错了什么。我试图以月视图方式呈现日历,如 calendar.app,但不幸的是,澳大利亚、英国等国家的一些用户报告天与日期的对齐不正确。例如,在澳大利亚,3 月 17 日显示为星期五。非常感谢任何帮助!
这是我正在使用的代码示例:
-(void)setCalendar
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:units fromDate:[NSDate date]];
self.currentDate = [gregorian dateFromComponents:comps];
NSInteger weekdayInteger=[comps weekday];
currentMonth=[comps month];
currentYear=[comps year];
NSString *dateString=[[NSString stringWithFormat:@"%@",currentDate] substringToIndex:10];
NSArray *array= [dateString componentsSeparatedByString:@"-"];
NSInteger currentDay=[[array objectAtIndex:2] intValue];
currentMonthConstant=currentMonth;
currentYearConstant=currentYear;
currentDayConstant=currentDay;
currentConstantDate=[NSString stringWithFormat:@"%d/%d/%d",currentDayConstant,currentMonthConstant,currentYearConstant];
currentFirstDay=((8+weekdayInteger-(currentDay%7))%7);
if(currentFirstDay==0)
currentFirstDay=7;
[gregorian release];
}
这就是我填充日历的方式:
-(void)fillCalender:(NSInteger)month weekStarts:(NSInteger)weekday year:(NSInteger)year
{
currentMonth=month;
currentYear=year;
currentFirstDay=weekday;
UIButton *temp;
NSInteger numberOfDays=[self getNumberofDays:month YearVlue:year];
currentLastDay=(currentFirstDay+numberOfDays-1)%7;
if(currentLastDay==0)
currentLastDay=7;
NSString *monthName=[self getMonth:month];
NSInteger grid=(weekday-1);
monthLabel.text=[NSString stringWithFormat:@"%@ %d",monthName,year];
for(int i=1;i<=numberOfDays;i++)
{
if([frontView isEqualToString:@"view1"])
temp=[arr_View2Buttons objectAtIndex:grid];
else
temp= [arr_View1Buttons objectAtIndex:grid];
[temp setBackgroundImage:nil forState:UIControlStateNormal];
[temp setUserInteractionEnabled:TRUE];
UILabel *aLbl = (UILabel *)[temp viewWithTag:123];
[aLbl setText:[NSString stringWithFormat:@"%d",i]];
// check for today
if(currentDayConstant == i && currentMonthConstant == currentMonth && currentYearConstant == currentYear)
{
[aLbl setTextColor:[UIColor blueColor]];
}
else
{
[aLbl setTextColor:[UIColor colorWithRed:69/255.0 green:2/255.0 blue:71/255.0 alpha:1.0]];
}
[temp setTag:i];
grid++;
if(grid==35)
grid=0;
}
}
最后是 viewdidload:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setCalendar];
// set views
[self.view1 setFrame:CGRectMake(0,45,320,232)];
[self.view2 setFrame:CGRectMake(0,277,320,232)];
[self.view addSubview:self.view1];
[self.view addSubview:self.view2];
frontView = @"view2";
[self fillCalender:currentMonth weekStarts:currentFirstDay year:currentYear];
frontView = @"view1";
}
After trying to work on someone else's code, and so many different iterations, I am unable to understand what am I doing wrong with dates on a calendar month view. I am trying to present a calendar in month view fashion like calendar.app but unfortunately some users in countries like Australia, UK are reporting incorrect alignment of Days to Dates. For instance in Australia it displays 17th March as Friday. Any help is highly appreciated!
Here is the code sample I am using:
-(void)setCalendar
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:units fromDate:[NSDate date]];
self.currentDate = [gregorian dateFromComponents:comps];
NSInteger weekdayInteger=[comps weekday];
currentMonth=[comps month];
currentYear=[comps year];
NSString *dateString=[[NSString stringWithFormat:@"%@",currentDate] substringToIndex:10];
NSArray *array= [dateString componentsSeparatedByString:@"-"];
NSInteger currentDay=[[array objectAtIndex:2] intValue];
currentMonthConstant=currentMonth;
currentYearConstant=currentYear;
currentDayConstant=currentDay;
currentConstantDate=[NSString stringWithFormat:@"%d/%d/%d",currentDayConstant,currentMonthConstant,currentYearConstant];
currentFirstDay=((8+weekdayInteger-(currentDay%7))%7);
if(currentFirstDay==0)
currentFirstDay=7;
[gregorian release];
}
And this is how im populating the calendar:
-(void)fillCalender:(NSInteger)month weekStarts:(NSInteger)weekday year:(NSInteger)year
{
currentMonth=month;
currentYear=year;
currentFirstDay=weekday;
UIButton *temp;
NSInteger numberOfDays=[self getNumberofDays:month YearVlue:year];
currentLastDay=(currentFirstDay+numberOfDays-1)%7;
if(currentLastDay==0)
currentLastDay=7;
NSString *monthName=[self getMonth:month];
NSInteger grid=(weekday-1);
monthLabel.text=[NSString stringWithFormat:@"%@ %d",monthName,year];
for(int i=1;i<=numberOfDays;i++)
{
if([frontView isEqualToString:@"view1"])
temp=[arr_View2Buttons objectAtIndex:grid];
else
temp= [arr_View1Buttons objectAtIndex:grid];
[temp setBackgroundImage:nil forState:UIControlStateNormal];
[temp setUserInteractionEnabled:TRUE];
UILabel *aLbl = (UILabel *)[temp viewWithTag:123];
[aLbl setText:[NSString stringWithFormat:@"%d",i]];
// check for today
if(currentDayConstant == i && currentMonthConstant == currentMonth && currentYearConstant == currentYear)
{
[aLbl setTextColor:[UIColor blueColor]];
}
else
{
[aLbl setTextColor:[UIColor colorWithRed:69/255.0 green:2/255.0 blue:71/255.0 alpha:1.0]];
}
[temp setTag:i];
grid++;
if(grid==35)
grid=0;
}
}
And finally viewdidload:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setCalendar];
// set views
[self.view1 setFrame:CGRectMake(0,45,320,232)];
[self.view2 setFrame:CGRectMake(0,277,320,232)];
[self.view addSubview:self.view1];
[self.view addSubview:self.view2];
frontView = @"view2";
[self fillCalender:currentMonth weekStarts:currentFirstDay year:currentYear];
frontView = @"view1";
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用 NSDateComponents 获取工作日、月份和年份。这很好。
但随后你可以使用字符串操作来获得这一天。
然后你可以操作从 NSDate 的描述方法中获得的字符串。根据我的经验,这个方法会返回它想要的任何内容。我永远无法弄清楚描述方法使用哪个时区偏移,在我的机器上它返回 UTC 时区的 NSDate,其他用户提出了有关 SO 的问题,这意味着该方法返回本地时区或以下时区的 NSDate位于当地时区旁边。或者在任意时区。通常这没有问题,因为您可以使用时区信息,但您只需忽略它即可。
长话短说:如果您想要日期处理,请不要使用字符串处理
恕我直言,这是一个时区问题。因为您混合了两种不同的日期处理方式,并且忽略了时区。
摆脱字符串操作部分并使用 NSDateComponents 来处理所有事情。
You use NSDateComponents to get the weekday, the month and the year. Which is fine.
But then you use string manipulation to get the day.
And you manipulate the string you get from the description method of NSDate. And from my experience this method returns whatever it wants. I could never figure out which timezone offset the description method uses, on my machine it returns the NSDate in UTC timezone, other users have asked questions on SO that imply that this method returns the NSDate in the local timezone, or in a timezone that is next to the local timezone. Or in a arbitrary timezone. Usually this is no problem because you can use the timezone information, but you simply ignore it.
To make a long story short: Do not use string processing if you want date processing
IMHO this is a timezone issue. Because you mix two different ways of date processing, and you ignore the timezone.
Get rid of the string manipulation part and use NSDateComponents for everything.
您需要更改代码
替换
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
与
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
这将识别设备中的当前日历并相应地执行
希望这能解决您的问题...
You need to change the code
replace
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
with
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
this will identify the current calendar from the device and will perform accordingly
Hope this will solve your problem...