Здравствуйте!
— Не хотите ли войти
3
ответа

NSDateComponents ошибочно определяет день недели

Прошу помощи в таком вопросе: имеется код для того чтобы выяснить, с какого дня недели начинается месяц.

NSDateComponents *comps = [[NSCalendar currentCalendar] 
    components:NSYearCalendarUnit|NSMonthCalendarUnit fromDate:someDate];
[comps setDay:1];

NSDateComponents *weekdayComponents =[[NSCalendar currentCalendar] 
    components:NSDayCalendarUnit|NSWeekdayCalendarUnit fromDate:[[NSCalendar currentCalendar] 
    dateFromComponents:comps]];

return [weekdayComponents weekday];

Раньше все время тестил программу в английской локали и проблем не было. Но вот поставил на свой айфон в русской локали и всплыл странный глюк: в календаре, где неделя начинается с понедельника (а не с воскресенья, как на Западе), return [weekdayComponents weekday]; всегда возвращает неверный день недели. То есть, у в календаре, который я делаю, например, этот месяц, 1 июля 2010, начинается в пятницу, хотя реально месяц начинается в четверг. На английской локали проблем нет. Где копать, помогите, пожалуйста! Не верю, что нету метода получать локализованные номера дней недели по дате.

16 июля 2010

Ответы

Вобщем, победил тем, что вручную задал значения, если первый день недели — понедельник. Однако, неудобно.

16 июля 2010

Я бы предложил такой алгоритм:

  • Я знаю, что 1 января 1970 года — четверг;
  • Я могу очень просто получить количество дней оттуда: (((int) [[NSDate date] timeIntervalSince1970]) / 86400) % 7;
  • При этом я получил, что 0 — это четверг. То есть нужно вычесть нужное количество, чтобы получить, что 0 — это понедельник, например: (((int) [[NSDate date] timeIntervalSince1970] — 3) / 86400) % 7

Как-то так.

16 июля 2010

А то с календарями действительно всегда фигня получается. Я примерно понимаю, почему он неправильно показывает, но кроме грегорианского календаря есть еще и другие… и тогда вообще непонятно, что делать.

alex

Ну алгоритм, реализованный мной, проще имхо для процессора афони. У меня к Вам просьба. Не могли бы Вы помочь мне все-таки разобраться с проблемой анимации выделения custom uitableviewcell (в теме на ru_iphonedev, где мы уже общались). Я там описал нюансы. Я прописал рендеринг ячейки вручную, скорость стала нормальной (ну нормальной для iOS 4.0, т.к. в ней даже списки в родных приложениях притормаживают немного), однако ячейка не анимирует снятие выделения. Как это реализовать не знаю. Если не трудно.

TOVVV

А то с этим я факт сам не разберусь. Даже за что хвататься не знаю. В коде все прописано, и фон прозрачным на момент выделения становится. Однако super ячейка при снятии выделения «сбрасывает» фон плавно, а моя custom ячейка, не смотря ни на что, в долю секунды меняет прозрачный фон на стандартный белы. Получается какашка.

TOVVV

Этот алгоритм для айфони — даром. Предыдущий затратнее, там математика тоже такая же простая, но ее раз в 5 больше минимум.

alex

Сомневаюсь, что NSDateComponents ошибочно что-то определяет. Предполагаю, что вы не до конца разобрались, как правильно использовать календари. У разных календарей разная нумерация дней недели. Поскольку вы берете текущий (currentCalendar) календарь, вы не можете гарантировать, что там первый день это понедельник или воскресенье.

Чтобы избежать проблем, я бы посоветовал всегда пользоваться одним календарем, например, грегорианским. У него первый день это воскресенье. Немного модифицируем ваш код:

//	The weekday value for Sunday in the Gregorian calendar is 1
	NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
	NSDateComponents *comps = [gregorian components:NSYearCalendarUnit|NSMonthCalendarUnit 
	fromDate:[NSDate date]];
	[comps setDay:1];
	
	NSDateComponents *weekdayComponents = [gregorian components:NSDayCalendarUnit|NSWeekdayCalendarUnit 
	fromDate:[gregorian dateFromComponents:comps]];

Сейчас июль, первый день — четверг, номер у него 5. Что мы и видим.

Насколько я понимаю, что этот код будет всегда работать корректно, и безо всяких костылей.

16 июля 2010

У грегорианского календаря тоже может быть разные «первые» дни. И европа и америка пользуется Грегорианским календарем, но дни разные.

Да, NSDateComponents (NSCalendar на самом деле) все определяет правильно. А метод firstWeekDay — выдает индекс первого дня недели (в америке это будет Sunday, у нас — Monday). А не то, что хочется.

Вроде так :)

alex

Нет, не так. У грегорианского календаря первый день — вс (согласно эпловской документации, сам не проверял).

firstWeekDay не поможет — он выдает номер первого дня, но не отвечает на вопрос, что этот номер значит. Скажем, вернет он 1 — это пон или вс?

bmikle

«Weekday units are the numbers 1 through n, where n is the number of days in the week. For example, in the Gregorian calendar, n is 7 and Sunday is represented by 1.»

То есть 1 — всегда воскресенье.

А firstWeekday вернет 1 для США и 2 для России.

И, это, Грегорианский календарь говорит про сколько дней в году. Там на недели наплевать :)

alex

Я писал, что если использовать Грегорианский календарь, то 1 всегда будет воскресеньем, и не надо писать костылей с вычеслениями от 1970 года и прочее. В чем проблема-то?

bmikle

Мы как всегда об одном и том же. Просто поправь firstWeekDay, замени на weekday что-ли, или как там его.

alex

Сорри. Последнюю строку вообще надо удалить — это остатки моих экспериментов :) Суть, короче, в том, что если использовать грегорианский календарь то все зашибись.

P. S. А поправить ничего не могу — кнопка «Отослать отредактированный ответ» не работает :( И даже не воспринимается как кнопка.

bmikle

Работает верхний правый угол этой кнопки, примерно один пиксель. Это фича такая. Пока я ее не исправил — фича :)

И ответы в почту приходят чертикак. Но сегодня не было сил исправлять. Может быть завтра сделаю.

alex
Зарегистрируйтесь или войдите, чтобы добавить свой комментарий или ответ на вопрос.
© 2009-2012, ООО «Инру»
Вход
Имя пользователя:
Пароль:
Или…
Twi
Отмена
Войти
Восстановить забытый пароль…