Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 225
Текст из файла (страница 225)
Базовым годом обычно является год 1970; точным базовым временем при этом является 0;00, ! января по Гринвичу. Если же Ите 1 — это 32-битное юпг, то уже к 2038 году мы окажемся «вне времени», если, конечно, не перейдем на более длинные тг, как это уже сделано на некоторых системах. Тип 1!те г предназначен для работы с относительно близкими датами, так что нельзя гарантировать его работу вне диапазона [!902,2038[. Еше хуже то, что не все реализации функций для работы со временем одинаково работают с отрицательными значениями. Для переносимости требуется, чтобы значение, которое нужно представлять и как Ите г, и как «л, лежало в диапазоне [1902,2038].
Для представления дат вне этого диапазона нужен какой-либо иной механизм. Одним из следствий вышесказанного является тот факт, что функция тйИте() может отработать некорректно. Для аргументов, которые не представимы типом Ите 1, она возвращает индикатор ошибки «те г(-1) . Хронометраж в программах с большим временем работы можно выполнить следующим образом: 1049 ().4. Стандартные фасеты 0.4.4.2. Класс (лате сймв Ваге ( риЬНс: епит Моптй (1аи=1,~еЬ, тиаг, арг, тау, 1ии, )и1, аил, вер, ост, иог, йес ); с(авлВай йоге (); Ваге (тт йй, Моптй тт, йгг уу); Ваге (); 3г1епй овтгеата орега(ог«(олггеата в, сопи Васев й) // ... ргйиасе: йте 1й( )' //стандартное представление даты и времени Х)ате:: Ваге ((пг йй, Моптй тт, шт уу) ( пих= (О) т (1'(йй<0 ) ) 31<01) тйгопВай йоте() т //переупрощеног см.
310.3.1 х.ии пЫау = ййг (у(тт<1ап ( ( йес<тт) гйгоп Вай йоге () 1 х.гт тои = ппи-1; //(т топ отсчитывается с нуля х.ии уеаг = уу — 10001 // тт уеаг отсчитывается от 1900 й = т(ийие(ах); ) ХЬие:: Ваге ( ) ( й = тйпе(0) т //умолчательный Вате: сегодня 13"(й == тйие 1(-1) ) ейгоп Вой йоге(); ) Теперь перед нами встает задача определить операции «и» для класса Вате, которые были бы чувствительны к локализации. (л.4.4.3. Вывод дат и времени как и пит рит (513.4.2), фасет пте риг предоставляет функции рит () для записи в буферы через итераторы: гетр)аге<с1ат Сй, с1ат Оит = олггеатйиХ йега1ог<СЬ» с1алв лЫ::Вте рш: риЫ1с!оса(е::Хосе( ( риЫтс: (урейе~'СЬ сйаг (урет турейеуОит 1гег туре) Как упоминалось в 510.3, маловероятно, чтобы единственный тип Х)аге мог удовлетворить все потребности.
Различные способы использования дат диктуют разные способы их представления, а календарная информация до !9 столетия сильно зависит от капризов истории. Тем не менее, в качестве примера мы можем определить тип Ваге примерно как в 510.3, используя для реализации Вте С 1050 Приложение Р. Локализация ехр!(с(< цте рш(з!<е < г = О) <У помещаем < в буфер потока з через Ь по формату/т<: Ои<ри<(Оп< Ь, !оз Ьазеь з, СЬ/ю!1, сола< оп* <, сола< СЬ*ут< Ь, сопз< СЬ* /т< е) сопз<ю Ои<ри<(Ои< Ь, юоз Ьазеа з, СЬ/ю!1, сопз«т* <, слог/т<, сьаг тою< = О) соле< (ге<игл ю<о ри<(Ь, з, 1(!1, <,/юп<, тою<) ю ) <данс !оса!е: ю ы !ю<ю <объект идентификации фасета (зР 2 зРЗ, зРЗ.!) реп<ее<ею<: -июпе ри<() „. г!г<иа! Оию ю<о ри<(Ои<, !оз Ьазеь, СЬ, солт ип*, слог, сваг) сопз<ю )ю Вызов рв1 (Ь, з,/111, <,Яюю< Ь,Я<«е) помещает информацию о дате из <в буфер потока з через Ь.
Символ <ю!! используется в качестве заполняющего. Формат вывода специфицируется рг!пр() -подобной строкой Яп< Ь,,!1<<< е). Этот рг!пр() -подобный формат (821.8) используется для порождения настоящего вывода и может содержать следующие форматные спецификаторы ° %а сокращение для дня недели (например, Ба() ° %А полное название дня недели (например, Ба(цг((ау) ° %Ь сокращенное название месяца (например, ГеЬ) ° %В поЛное название месяца (например, ГеЬпюагу) ° %с дата и время (например, Ба( РеЬ 06 21;46:05 1999) ° %<) число [01,31] (например, 06) ° %Н 24-часовой формат времени [00,23] (например, 2!) ° %1 12-часовой формат времени [01,12] (например, 09) ° %] день года [001,366] (например, 037) ° %щ месяц [01,12] (например, 02) ° %М минута часа [00,59] (например, 48) ° %р а щ/р.щ индикатор для 12-часового формата (например, РМ) ° %8 секунда в минуте [00,61] (например, 40) ° %Б неделя года [00,53] начиная с воскресенья (например, 05) ° %чю день недели [0,6], где 0 это воскресенье (например, 6) ° %чч' неделя года [00,53] с понедельника (например, 05) ° %х дата (например, 02/06/99) ° %Х время (например, 21:48:40) ° %у год без века [00,99] (например, 99) ° %У год (например, 1999) ° %с.
индикатор часового пояса (например, ЕБТ), если он известен Этот длинный список форматных спецификаторов может послужить наглядным аргументом в пользу расширяемой системы ввода/вывода. Однако как и всякая специализированная система обозначений она точна и даже, до некоторой степени, удобна. ().4. Стандартные фасеты 1051 Кроме перечисленных директив форматирования многие реализации поддерживают «модификаторы», такие как, например, целые модификаторы ширины поля вывода 52(.8), .10Х.
Модификаторы форматов дат и времени не являются частью стандарта С++, в то время как стандарты некоторых платформ, например РОБ1Х, требуют их. Поэтому избежать применения модификаторов трудно, несмотря на то, что их применение снижает переносимость программы. Функция яяги(те() из <опте> или <пте.й>, подобная функции ярг1п(1() (521.8), производит вывод в соответствии с директивами форматирования дат и времени: я(яе 111»211те(сйаг* я, 11йе 1 тих, солт сйаг*/огта1, соля! ии* 1тр) 1 Эта функция помешает максимум тах символов из *пир в *я согласно формату )огтаг. Например: тг лнип () ( соил( глг 1иах = 20; УУ надеемся, что я(ф(те() не произведет более 20 символов сйаг Ьит(тах) 1 Ите 11= Ите(0); ягг))(те ( Ьит, тах, " »г«А ~ и ", (осаййте ( й1) ) 1 сои( «Ьит) ) Для дня недели «среда» эта программа выведет )ЬеИиеЫау в контексте локализации «по умолчанию» с1аяяяс() (ййл.2.3), и оаЫая для датской локализации.
Символы, не являющиеся частью формата, такие как «перевод строки» в данном примере, просто копируются в *я. Когда риг() обнаруживает символ форматирования 1'(и необязательный модификатор т), то для выполнения форматирования она вызывает виртуальную функцию Ио риг() с соответствующими параметрами: Ио ри1(Ь,я, ЯИ,1,~, т) . Вызов риг(Ь,я, ИИ, 1,1',т) является упрощенным вариантом риг(), в котором символ форматирования("и модификатор т задаются явным образом.
Таким образом, фрагмент соля1 сйагГтг() = "%10Х" 1 рт (Ь, я, ()И, 1,1т1,1тг»я(йео1'(Гтг) ) 1 можно сократить до ри1(Ь,я,1)И,1, 'Х',10) 1 Если формат содержит мультибайтные символы, он должен и начинаться, и заканчиваться в состоянии «по умолчанию» (вйл.4.6). Мы можем применить функцию риг (), чтобы реализовать зависящую от контекста локализации операцию 'вывода для типа Риге: оя(геатй орега1ог«(отгеатй я, соля( Рагей и) ( ояоеат::яепиу яиап!(я) 1 УУ см. 82!.3.8 (Т(!8иап$) ге1игп я) 1т* ипр = 1оса11(те ( йд. 0) ягу 1052 Приложение ().
Локализация ( (Г(иееГасег<11те рт<слаг» (е.йейос () ) .рог (е, з, «.5)й () „гтр, 'х' ) .Гойей() ) з.еееааге(/ое Ьаее: ."ГайЬ11) г ) сагсЬ (... ) ( папа/е (оексерг(оп (е); й см. 51)А.2.2 ) гегигп з; Поскольку никакого стандартного типа Ваге не существует, нет и стандартного формата «по умолчанию» для ввода/вывода дат. Здесь я задал формат ьх, передавая символ 'х' в качестве символа форматирования.
Поскольку формат ах является форматом «по умолчанию» для аег йте() (ВР.4.4.4), то он является по сути дела «наиболее стандартным». Имеется и версия пте риг с суффиксом Ьупате (ВР.4, ВГ).4.1): гетр(аге<с1ат СЬ, с1ат Оиг = оеггеатЬи~' йегагог<СЬ> > с1ат «14::йте риг Ьупате: риЫ!с йте ри«СЬ, От> (/* ... */); 0.4.4.4. Ввод дат и времени Как всегда, ввод несколько сложнее вывода. Когда мы пишем код для вывода значения, у нас обычно есть выбор между несколькими разными форматами. А когда мы пишем код для ввода, мы должны в первую очередь следить за ошибками и, лишь иногда, выбирать из нескольких форматных альтернатив.
Фасет пте ~ег реализует ввод дат и времени. Идея заключается в том, что фасет Пте яег может читать форматы времени и дат, которые в данной локализации порождает фасет Пте ри1 Ввиду отсутствия стандартных классов времени и дат, программист в рамках контекста локализации может осуществлять вывод согласно множеству форматов. Например, все приведенные ниже представления могут бьггь получены с помощью одной и той же операции вывода, использующей фасет пте ри( (ВР.4.4.5) разных локализаций: уапиагу 15сй 1999 ТЬигейау 151Ь Яапиагу 1999 15 Уап 1999АЭ ТЬиге 15/1/99 Стандарт С++ поощряет разработчиков Пте яе1 воспринимать форматы дат и времени в соответствии с РОВ(Х и иными распространенными промышленными стандартами.
Главная трудность состоит в том, что почти невозможно стандартизировать намерение читать даты и время во всех мыслимых форматах, принятых в рамках разнообразных местных и национальных (шире — культурных) соглашений. Можно поэкспериментировать, чтобы поточнее познакомиться с возможностями конкретного контекста локализации (Вг().6[8)). Если формат не воспринимается, программист может реализовать необходимый ему альтернативный фасет пте «ег сам. Стандартный фасет для ввода времени, Пте аег, наследуется от класса Пте Ьаее: () 4. Стандартные фасеты 1053 тгисс зЫ:: Ите Ьазе ( епигп ИасеогИег ( по огдег, Иту, тИу, упЫ, уИт )' У не упорядочено г7 день-месяц-год ~У месяц-день-год II год-месяц-день У год-день-месяц Разработчик может воспользоваться этим перечислением для упрощения анализа форматов даты.