I need to convert Julian dates (fetched from the API) to Gregorian dates. I followed the following link: Converting a Gregorian date to Julian Day Count in Objective C. But, the year component comes confusing by both ways (1):
NSInteger julianDays = 1580198400;
NSUInteger julianDayFor01012000 = 2451545;
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDateComponents *comp = [[NSDateComponents alloc] init];
comp.year = 2000;
comp.month = 1;
comp.day = 1;
NSDate *ref = [cal dateFromComponents:comp];
NSDateComponents *diff = [[NSDateComponents alloc] init];
diff.day = julianDays - julianDayFor01012000;
NSDate *date = [cal dateByAddingComponents:diff toDate:ref options:0];
comp = [cal components:NSCalendarUnitDay|NSCalendarUnitMonth|NSCalendarUnitYear fromDate:date];
Output: Calendar Year: 4321724 Month: 3 Leap month: no Day: 3
And (2):
NSInteger julianDays = 1580198400;
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:#"g"];
NSDate *date = [fmt dateFromString:[#(julianDays) stringValue]];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comp = [cal components:NSCalendarUnitDay|NSCalendarUnitMonth|NSCalendarUnitYear fromDate:date];
Output: Calendar Year: 4321724 Month: 3 Leap month: no Day: 3
Why is the year coming as 4321724? Do I have to interpret it further? Any help would be appreciated.
Related
I have to find next Sunday date (NSDate) from device's current date.
I have used below logic:
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar components:NSCalendarUnitWeekday | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
NSUInteger weekdayToday = [components weekday];
NSInteger daysToMonday = (8 - weekdayToday) % 7;
NSDate *weekEndPrev = [self dateByAddingTimeInterval:60*60*24*daysToMonday];
Here, in EST if time is near to 11 PM, I'm getting Monday as Weekend.
Let me know feasible solution. I have tried many options. Nothings works with 2 different timezones.
Thanks in Advance.
You need just to get the number of days you need and then just add them to your current date:
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate * newDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:value toDate:date options:0];
where value - is the number of days to add
Find current week Sunday Date first then add 7 days using NSDateComponents.
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *weekdayComponents = [gregorian components:NSCalendarUnitWeekday fromDate:today];
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
[componentsToSubtract setDay:(0 - ([weekdayComponents weekday] - 1))];
NSDate *sudayCurWeek = [gregorian dateByAddingComponents:componentsToSubtract toDate:today options:0];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:7];
NSDate *nextSunday = [gregorian dateByAddingComponents:offsetComponents toDate:sudayCurWeek options:0];
NSLog(#"%#",nextSunday);
You can do this without any math, which is best left to NSCalendar as it handles daylight savings etc. First you need a calendar with the correct time zone. For example for IST:
NSCalendar *gc = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
gc.timeZone = [NSTimeZone timeZoneWithName:#"IST"];
Then you can use nextDateAfterDate:matchingUnit:value:options: to find the start of the next Sunday after a given time. For example:
NSDate *start = ... // the time you wish to start from
NSDate *nextSunday =
[gc nextDateAfterDate:start
matching:UnitNSCalendarUnitWeekday // match based on weekday number
value:1 // Sunday = weekday 1
options:NSCalendarMatchNextTime // read the docs!
];
The returned date, nextSunday, will be the next Sunday at 00:00 in the timezone of the calendar, gc.
HTH
Finally, I got solution..
NSDateComponents *components = [[NSCalendar currentCalendar] componentsInTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"] fromDate:[NSDate date]]; // Pass date for which you want to find next Sunday
NSUInteger weekdayToday = [components weekday];
NSInteger daysToMonday = (8 - weekdayToday) % 7;
NSDate *weekEndPrev = [[NSDate date] dateByAddingTimeInterval:60*60*24*daysToMonday];
I have a requirement in which i have to calculate working days i.e from Monday to Friday. if i pass todays date that particular week start date (Monday's Date) and end date(Friday's Date) will be displayed. And i calculated using the below Code.
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd"];// you can use your format.
todayDate= [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:todayDate];
int dayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:todayDate] weekday];// this will give you current day of week
[components setDay:([components day] - ((dayofweek) - 2))];// for beginning of the week.
NSDate *beginningOfWeek = [gregorian dateFromComponents:components];
NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init];
[dateFormat_first setDateFormat:#"yyyy-MM-dd"];
NSString * dateString2Prev = [dateFormat stringFromDate:beginningOfWeek];
NSDate * weekstartPrev = [dateFormat_first dateFromString:dateString2Prev];
// NSLog(#"The start of the week %#",weekstartPrev);
startDate= [weekstartPrev dateByAddingTimeInterval:60*60*24*1];
//NSLog(#"The date plus one is %#", startDate);
//Week End Date
NSCalendar *gregorianEnd = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsEnd = [gregorianEnd components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:todayDate];
int Enddayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:todayDate] weekday];// this will give you current day of week
[componentsEnd setDay:([componentsEnd day]+(7-Enddayofweek)+1)];// for end day of the week
NSDate *EndOfWeek = [gregorianEnd dateFromComponents:componentsEnd];
NSDateFormatter *dateFormat_End = [[NSDateFormatter alloc] init];
[dateFormat_End setDateFormat:#"yyyy-MM-dd"];
NSString *dateEndPrev = [dateFormat stringFromDate:EndOfWeek];
NSDate *weekEndPrev = [dateFormat_End dateFromString:dateEndPrev];
endDate= [weekEndPrev dateByAddingTimeInterval: -86400.0];
NSDateFormatter *dateF = [[NSDateFormatter alloc] init];
[dateF setDateFormat:#"dd-MMM-yyyy"];
[dateF setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateF setLocale:[NSLocale localeWithLocaleIdentifier:#"en_GB"]];
endDateString = [dateF stringFromDate:endDate]; //pass this date to time table view controller
NSLog(#"Start date %# and End date %# ",startDate, endDate);
NSDateFormatter *dateF = [[NSDateFormatter alloc] init];
[dateF setDateFormat:#"dd-MMM-yyyy"];
[dateF setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateF setLocale:[NSLocale localeWithLocaleIdentifier:#"en_GB"]];
startDateString = [dateF stringFromDate:startDate];
NSLog(#"the date start %# ", startDateString);
Now My question is how can I calculate next week for example todays date is Tue 26 Aug 2014. I calculated the current week i.e from Mon 25 Aug 2014 TO Fri 29 Aug 2014 using the above code. how can I calculate next week i.e from 1st September 2014 (monday) To 5th September 2014 (Friday).
i have worked on the similar issues some weeks ago.
I created a category on NSDate. You can use the methods.
- (NSDate *)firstDayOfWeek
{
return [NSDate firstDayOfWeekFor:self];
}
+(NSDate *)firstDayOfWeekFor:(NSDate*)p_Date
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *weekdayComponents = [calendar components:NSWeekdayCalendarUnit fromDate:p_Date];
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
if ([weekdayComponents weekday] == 1)
{
// dimanche, on soustrait 6 jours
[componentsToSubtract setDay:-6];
}
else
{
// autres jours, on soustrait le jour courant et on rajoute 2 (=lundi)
[componentsToSubtract setDay:(-[weekdayComponents weekday] + 2)];
}
return [calendar dateByAddingComponents:componentsToSubtract toDate:[p_Date withoutTime] options:0];
}
- (NSDate *) dateByAddingDays:(NSInteger)p_Days
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:p_Days];
return [calendar dateByAddingComponents:components toDate:self options:0];
}
I am using following piece of code to get next week date from a given date at 12:00am:
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit |NSHourCalendarUnit fromDate:now];
[components setHour:0];
NSDate *todayDate = [calendar dateFromComponents:components];
int daysToAdd = 7;
NSDate *tomorrowDate = [todayDate dateByAddingTimeInterval:60*60*24*daysToAdd];
NSString *stringDate = [NSString stringWithFormat:#"%#",tomorrowDate];
todoItemDueDateText.text = stringDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechasimulada = [dateFormatter stringFromDate:tomorrowDate];
dateFieldSimulatedText.text = fechasimulada;
If I log the result date, it is working fine.
Now, a similar piece of code to get next month date from a given date at 12:00am:
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
[components setHour:0];
NSDate *todayDate = [calendar dateFromComponents:components];
//NSDate *today = [NSDate date];
NSDateComponents* dateComponents = [[NSDateComponents alloc]init];
[dateComponents setMonth:1];
//NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* tomorrowDate = [calendar dateByAddingComponents:dateComponents toDate:todayDate options:0];
NSString *stringDate = [NSString stringWithFormat:#"%#",tomorrowDate];
todoItemDueDateText.text = stringDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechasimulada = [dateFormatter stringFromDate:tomorrowDate];
I don't know why, but the second piece of code gives the expected date but -1 hour.
UPDATE:
I will show you the dates:
Source date (today at 12:00am)+7 h
Next week date from previous given date:
Next month date from previous given date:
NSDate takes Daylight Savings into account. If you cross a DST day, you'll experience this issue.
I need to get the weekday of the first day of the month. For example, for the current month September 2013 the first day falls on Sunday.
At first, get the first day of current month (for example):
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:today];
components.day = 1;
NSDate *firstDayOfMonth = [gregorian dateFromComponents:components];
Then use NSDateFormatter to print it as a weekday:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEEE"];
NSLog(#"%#", [dateFormatter stringFromDate:firstDayOfMonth]);
P.S. also take a look at Date Format Patterns
Here is the solution to getting the weekday name of the first day in the current month
NSDateComponents *weekdayComps = [[NSDateComponents alloc] init];
weekdayComps = [calendar.currentCalendar components:calendar.unitFlags fromDate:calendar.today];
weekdayComps.day = 1;
NSDateFormatter *weekDayFormatter = [[NSDateFormatter alloc]init];
[weekDayFormatter setDateFormat:#"EEEE"];
NSString *firstweekday = [weekDayFormatter stringFromDate:[calendar.currentCalendar dateFromComponents:weekdayComps]];
NSLog(#"FIRST WEEKDAY: %#", firstweekday);
For the weekday index, use this
NSDate *weekDate = [calendar.currentCalendar dateFromComponents:weekdayComps];
NSDateComponents *components = [calendar.currentCalendar components: NSWeekdayCalendarUnit fromDate: weekDate];
NSUInteger weekdayIndex = [components weekday];
NSLog(#"WEEKDAY INDEX %i", weekdayIndex);
You can also increment or decrement the month if needed.
Depending on the output you need you may use NSDateFormatter (as it was already said) or you may use NSDateComponents class. NSDateFormatter will give you a string representation, NSDateComponents will give you integer values. Method weekday may do what you want.
NSDateComponents *components = ...;
NSInteger val = [components weekday];
For Swift 4.2
First:
extension Calendar {
func startOfMonth(_ date: Date) -> Date {
return self.date(from: self.dateComponents([.year, .month], from: date))!
}
}
Second:
self.firstWeekDay = calendar.component(.weekday, from: calendar.startOfMonth(Date()))
Scenario:
I have an expense tracking iOS Application and I am storing expenses from a expense detail view controller into a table view (with fetched results controller) that shows the list of expenses along with the category and amount and date. I do have a date attribute in my entity "Money" which is a parent entity for either an expense or an income.
Question:
What I want is to basically categorize my expenses for a given week, a month, or year and display it as the section header title for example : (Oct 1- Oct 7, 2012) and it shows expenses amount and related stuff according to that particular week. Two buttons are provided in that view, if I would press the right button, it will increment the week by a week (Oct 1- Oct 7, 2012 now shows Oct8 - Oct 15, 2012) and similarly the left button would decrement the week by a week.
How would I accomplish that? I am trying the following code - doesn't work.
- (void)weekCalculation
{
NSDate *today = [NSDate date]; // present date (current date)
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:NSYearForWeekOfYearCalendarUnit |NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:today];
[comps setWeekday:1]; // 1: Sunday
firstDateOfTheWeek = [[calendar dateFromComponents:comps] retain];
[comps setWeekday:7]; // 7: Saturday
lastDateOfTheWeek = [[calendar dateFromComponents:comps] retain];
NSLog(#" first date of week =%#", firstDateOfTheWeek);
NSLog(#" last date of week =%#", lastDateOfTheWeek);
firstDateOfWeek = [dateFormatter stringFromDate:firstDateOfTheWeek];
lastDateOfWeek = [dateFormatter stringFromDate:lastDateOfTheWeek];
}
Code for incrementing date -
- (IBAction)showNextDates:(id)sender
{
int addDaysCount = 7;
NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setDay:addDaysCount];
NSDate *newDate1 = [[NSCalendar currentCalendar]
dateByAddingComponents:dateComponents
toDate:firstDateOfTheWeek options:0];
NSDate *newDate2 = [[NSCalendar currentCalendar]
dateByAddingComponents:dateComponents
toDate:lastDateOfTheWeek options:0];
NSLog(#" new dates =%# %#", newDate1, newDate2);
}
Suppose the week shows like this (Nov4, 2012 - Nov10, 2012) and I press the increment button, I see in the console, date changes to Nov11,2012 and Nov.17, 2012 which is right but if I press the increment button again, it shows the same date again (Nov 11, 2012 and Nov.17, 2012).
Please help me out here.
Declare currentDate as an #property in your class. And try this.
#property(nonatomic, retain) NSDate *currentDate;
Initially set
self.currentDate = [NSDate date];
before calling this method.
- (void)weekCalculation
{
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:NSYearForWeekOfYearCalendarUnit |NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:self.currentDate];
[comps setWeekday:1]; // 1: Sunday
firstDateOfTheWeek = [[calendar dateFromComponents:comps] retain];
[comps setWeekday:7]; // 7: Saturday
lastDateOfTheWeek = [[calendar dateFromComponents:comps] retain];
NSLog(#" first date of week =%#", firstDateOfTheWeek);
NSLog(#" last date of week =%#", lastDateOfTheWeek);
firstDateOfWeek = [dateFormatter stringFromDate:firstDateOfTheWeek];
lastDateOfWeek = [dateFormatter stringFromDate:lastDateOfTheWeek];
}
Once the view is loaded self.currentDate value should be updated from showNextDates. Make sure it is not getting reset anywhere else.
- (IBAction)showNextDates:(id)sender
{
int addDaysCount = 7;
NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setDay:addDaysCount];
NSDate *newDate1 = [[NSCalendar currentCalendar]
dateByAddingComponents:dateComponents
toDate:firstDateOfTheWeek options:0];
NSDate *newDate2 = [[NSCalendar currentCalendar]
dateByAddingComponents:dateComponents
toDate:lastDateOfTheWeek options:0];
NSLog(#" new dates =%# %#", newDate1, newDate2);
self.currentDate = newDate1;
}
I had needed similar thing in one of my old projects and achieved it via the code below. It sets this weeks date to an NSDate variable and adds/removes 7 days from day component in each button click. Here is the code:
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
NSDate *date = [NSDate date];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit|NSWeekdayCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date ];
//
[components setDay:([components day] - ([components weekday] )+2)];
self.currentDate = [calendar dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"dd.MM.yyyy HH:mm:ss";
self.datelabel.text = [formatter stringFromDate:self.currentDate];
The code above calculates this week start and sets it to currentDate variable. I Have two UIButtons with UIActions named prevClick and nextClick which calls the method that sets the next or previous weekstart:
- (IBAction)prevClick:(id)sender {
[self addRemoveWeek:NO];
}
-(void)addRemoveWeek:(BOOL)add{
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit|NSWeekdayCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:self.currentDate ];
components.day = add?components.day+7:components.day-7;
self.currentDate = [calendar dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"dd.MM.yyyy HH:mm:ss";
self.datelabel.text = [formatter stringFromDate:self.currentDate];
}
- (IBAction)nextClk:(id)sender {
[self addRemoveWeek: YES];
}