the following code
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setFirstWeekday:2];
[cal setMinimumDaysInFirstWeek:4];
NSDateComponents *comp = [[NSDateComponents alloc] init];
[comp setYear: 2012];
[comp setMonth:3];
[comp setDay: 12];
NSDate *date = [cal dateFromComponents:comp];
NSLog(#"date:%#",date);
logs:
date:2012-03-11 23:00:00 +0000
Any Idea, why this happen and how to avoid
Tnx
I assume you are using the CET time zone locally. This is what the [NSCalendar currentCalendar] will use as a time zone then.
When you dump a NSDate with NSLog, you will get the date in its raw UTC form. To print the date using a local format, look into the NSDateFormatter class, which has a timeZone property:
....
NSDate *date = [cal dateFromComponents:comp];
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
fmt.timeZone = [NSTimeZone defaultTimeZone]; // Probably not required
NSLog(#"date:%#", [fmt stringFromDate:date]);
set timezone
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
When you call dateFromComponents: you lose all of the timezone and calendar information and are left an NSDate object that contains the moment in time your date components represent, but nothing else. When you use NSLog on your NSDate object, that moment in time is converted to a time in UTC and rendered as a human readable string.
You need to provide more info about what you're trying to achieve to be able to answer your second question of how to avoid this.
Related
Im trying to figure out this timestamp format, but it looks weird to me.
There is a timestamp in that format: 184930.60
Explanation is: "This is UTC time since midnight in the form HH:MM:SS.SS."
It looks like number of seconds (based on change in file, for 20Hz GPS module), but it is 51h when you convert these seconds, and this can't be 51h after midnight.
Any idea how to convert that into nsdate?
Details about file format: https://racelogic.support/01VBOX_Automotive/01General_Information/Knowledge_Base/VBO_file_format
This is working example:
-(NSDate *)getDateFromDecimalTime:(double)decimalTime{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HHmmss.SS"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"UTC"]];
NSDate *date = [formatter dateFromString:[NSString stringWithFormat:#"%f", decimalTime]];
//gather current calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
//gather date components from date
NSDateComponents *dateComponents = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond) fromDate:date];
// Get current year/day/month
NSDate *now = [NSDate date];
// Specify which units we would like to use
unsigned units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar *calendar2 = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar2 components:units fromDate:now];
//set date components
[dateComponents setDay:[components day]];
[dateComponents setMonth:[components month]];
[dateComponents setYear:[components year]];
//save date relative from date
NSDate *completeDate = [calendar dateFromComponents:dateComponents];
return completeDate;
}
Suppose i have two parameters
Australia/Sydney (GMT+10) offset 36000 &
Asia/Kolkata (IST) offset 19800
as timezones, it gives different values for the day component of current day itself. I am not able to figure out what am i doing wrong.. :( A little clue will be appreciated
-(NSInteger)getDayWithTimeZoneName:(NSString *)timeZoneName{
// Instantiate a timezone
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:timeZoneName];
//Instantiate a date formatter
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setLocale:[NSLocale currentLocale]];
[df setTimeZone:timeZone];
[df setDateFormat:#"yyyy-MM-dd"];
NSString *dateStr = [df stringFromDate:[NSDate date]];
NSDate *date = [df dateFromString:dateStr];
// NSDateComponents *components = [[NSCalendar currentCalendar] components: NSCalendarUnitDay fromDate:date];
NSDateComponents *components = [[[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar]components:NSDayCalendarUnit fromDate:date];
NSInteger day = [components day];
NSLog(#"Date component for timeZone %# is %ld", timeZoneName,(long)day);
return day;
}
NSFormatter isn't designed to convert or calculate dates:
NSString *dateStr = [df stringFromDate:[NSDate date]];
dateStr is the date in Sydney (2016-05-16 0:00).
NSDate *date = [df dateFromString:dateStr];
date is GMT, 10 hours behind Sydney (2016-05-15 14:00).
Use NSCalendar to calculate dates:
NSCalendar *calendar = [NSCalendar currentCalendar];
calendar.timeZone = timeZone;
NSDateComponents *components = [calendar components:NSCalendarUnitDay fromDate:[NSDate date]];
NSInteger day = [components day];
I have a date in string format just like 30-11-2012. I want the date next to it like 01-12-2012 again in string format.
Is there any way of getting it?
You should use NSCalendar for best compatibility
NSDate *today = [NSDate dateWithNaturalLanguageString:#"2011-11-30"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dayComponent = [NSDateComponents new];
dayComponent.day = 1;
today = [calendar dateByAddingComponents:dayComponent toDate:today options:0];
//2011-12-01 12:00:00 +0000
I got the answer by someone I forget the name, I was about to accept his/her answer but when I clicked on accept answer it told me that the post bas been removed.
The answer given by that anonymous person was given below
NSString *dateString = #"22-11-2012";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSDate *dateFromString = [[NSDate alloc] init];
dateFromString = [dateFormatter dateFromString:dateString];
NSDateComponents *components= [[NSDateComponents alloc] init];
[components setDay:1];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *dateIncremented= [calendar dateByAddingComponents:components toDate:dateFromString options:0];
NSDateFormatter *myDateFormatter = [[NSDateFormatter alloc] init];
[myDateFormatter setDateFormat:#"dd-MM-yyyy"];
NSString *stringFromDate = [myDateFormatter stringFromDate:dateIncremented];
NSLog(#"%#", stringFromDate);
In the end I really like to thanks that anonymous person, I know this was not as much tricky but this helped me a lot. Thanks again you the Anonymous Helper.
swift 3.0
var components = DateComponents()
components.day = 1
let now = Date()
let futureDate = Calendar.current.date(byAdding: components, to: now, wrappingComponents: false)
//now = 2017-03-22 futureDate = 2017-03-23
I know there is a lot of questions of this type, but I did't find solution for my case;
I need to get current and correct NSDate object, not NSString!
This code returns wrong time (+3 hours), because I'm from Ukraine.
NSDate *currentDate = [NSDate date];
How to get current NSDate object from NSDateFormatter? I know only how to get NSString, but I don't need it.
EDIT: I'm using this code to compare 2 NSDates using NSCalendar object, here is code:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [calendar components:unitFlags fromDate:nowDate toDate:endDate options:0];
and components.hour shows me +3 hours difference
NSDates are always stored in UTC, actually the dates itselfs dont know anything about timezones or weeks, month, years. They are just a point in time.
To see the correct time for your position on the earth surface, you need to take the NSCalendar, that represents your time model in account. You could use it directly and mess around with your dates, or create a NSDateFormatter that will leave the dates untouched but adjust their appearence to your needs.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];
NSLog(#"%#", [formatter stringFromDate: date1]);
results in
Thursday, July 12, 2012, 4:36:07 PM Central European Summer Time
in response to the comment:
try this code as test
NSDate *now = [NSDate date];
NSDate *startOfToday = nil;
NSDate *startOfThisWeek = nil;
NSDate *startOfThisMonth = nil;
NSDate *startOfThisYear = nil;
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startOfToday interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit startDate:&startOfThisWeek interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startOfThisMonth interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSYearCalendarUnit startDate:&startOfThisYear interval:NULL forDate:now];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];
NSLog(#"%#", now);
NSLog(#"%#", [formatter stringFromDate:now]);
NSLog(#"%#", startOfToday);
NSLog(#"%#", [formatter stringFromDate:startOfToday]);
NSLog(#"%#", startOfThisWeek);
NSLog(#"%#", [formatter stringFromDate:startOfThisWeek]);
NSLog(#"%#", startOfThisMonth);
NSLog(#"%#", [formatter stringFromDate:startOfThisMonth]);
NSLog(#"%#", startOfThisYear);
NSLog(#"%#", [formatter stringFromDate:startOfThisYear]);
you will realize, that the start of the day, week, month and year will be adjusted to your local time, as the first of each NSLog-pair will give you the date in UTC and the second in your local time zone.
on the chat you posted this code
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd HH:mm"];
[dateFormat setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [dateFormat dateFromString:dateString];
[dateFormat release];
so the problem is, that the datestring is actually not from GMT, but EET (Eastern European Time)
try
[dateFormat setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"EET"]];
but the by far most elegant solution would be to get the datestring with the offset to UTC, similar to 2012-07-12 12:23:00 +0300if some how possible.
In such an case you could parse it with
[dateFormat setDateFormat:#"yyyy-mm-dd HH:mm:ss Z"];
and don't need further time zone handling, as the formatter knows the offset via the Z-specifier.
Also note, that if you don't set any timezone, the device's current should be used. If the user is always in the same timezone as the time from the date string, this should work, too. But if the user leaves that zone, or you inted to have it working world wide, you should use one of the solutions I gave you. With the second (specifying the timezone with-in the datestring) as the preferred one.
The date probably has the correct value; perhaps you think it's incorrect because it looks wrong when you log it? This is because when you log it, it shows the date in UTC. You can get the string in your local timezone by using an NSDateFormatter.
The answer is correct if the second date is in UTC. The Ukraine is currently 3 hours ahead of UTC so midnight UTC is at 21:00 in the Ukraine. 21:00 - 18:00 is 3 hours. So check how you are obtaining the second date. The wrong time zone is probably being specified for it.
If the first date really was created at 18:00 Ukraine time via
nowDate = [NSDate date];
then the second date really is 21:00 Ukraine time which corresponds to midnight UTC. Since you claim it is midnight, you must have used UTC to create it from a string - either implicitly or explicitly. Show us how you created it.
** EDIT **
The code you gave me on chat is this:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd HH:mm"];
[dateFormat setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [dateFormat dateFromString:dateString];
[dateFormat release];
The third line sets the time zone to GMT which is identical to UTC for all intents and purposes. Your date formatter is probably initialised to the correct locale for the device and so probably you can just leave that line out.
NSDate *now = [[NSDate alloc] init];
gives the current date.
However if the phone calendar is not Gregorian (on the emulator there is also Japanese and Buddhist), the current date will not be Gregorian.
The question now is how to convert to a Gregorian date or make sure it will be in the Gregorian format from the beginning. This is crucial for some server communication.
Thank you!
NSDate just represents a point in time and has no format in itself.
To format an NSDate to e.g. a string, you should use NSDateFormatter. It has a calendar property, and if you set this property to an instance of a Gregorian calendar, the outputted format will match a Gregorian style.
NSDate *now = [NSDate date];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setCalendar:gregorianCalendar];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];
NSString *formattedDate = [formatter stringFromDate:now];
NSLog(#"%#", formattedDate);
[gregorianCalendar release];
[formatter release];
The picked answer actually I can't compare them. only display is not enough for my project.
I finally come up with a solution that covert (NSDate) currentDate -> gregorianDate
then we can compare those NSDates.
Just remember that the NSDates should be used temporary .(it do not attach with any calendar)
NSDate* currentDate = [NSDate date];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *gregorianComponents = [gregorianCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:currentDate];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:[gregorianComponents day]];
[comps setMonth:[gregorianComponents month]];
[comps setYear:[gregorianComponents year]];
[comps setHour:[gregorianComponents hour]];
[comps setMinute:[gregorianComponents minute]];
[comps setSecond:[gregorianComponents second]];
NSCalendar *currentCalendar = [NSCalendar autoupdatingCurrentCalendar];
NSDate *today = [currentCalendar dateFromComponents:comps];