Есть ли верхний предел в моей локали для информации, связанной со временем?

Есть ли где-нибудь определение в стандартном пространстве имен, которое устанавливает вперед:

  1. Месяцы в году
  2. Дни в неделе
  3. Часы в день
  4. Минут в час
  5. Секунд в минуту

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

Я даже не уверен, есть ли локали, определенные там, где они не будут соответствовать обычному набору (12/7/24/60/60).

Даже если нет потенциальных пользователей с другими пределами диапазона, я бы определенно хотел использовать определение из стандартного пространства имен, а не произвольно определять свое собственное.

РЕДАКТИРОВАТЬ:

Похоже, я не первый, кто просит об этом: http://david.tribble.com/text/c0xcalendar.html
Я заметил, что в этом предложении есть упоминание о struct calendarinfo который делает именно то, что я ищу.

Похоже, что последнее изменение было в 2009 году. Думаю, с тех пор ничего не произошло? Я думаю, это также означает, что этот материал не доступен для меня?

Больше информации, повышение :: локали :: календарь :: максимум кажется, выполняет именно то, что я ищу. Я не могу использовать Boost, но я уверен, что код в Boost является стандарт defacto о том, как придумать эти ограничения. К сожалению, я не могу добиться реализации maximum, Может, кто-то еще здесь знает, как?

2

Решение

Стандарты C и C ++ абсолютно ничего не говорят ни о каком календаре, кроме григорианского, и не очень много о нем.

1. Месяцы в году

Единственное, что вы найдете, это комментарий в стандарте C рядом с tm_mon член tm:

int tm_mon;  // months since January -- [0, 11]

Ну, почти только. Вы также найдете %b а также %B спецификаторы в strftime которые соответствуют сокращенным и полным названиям текущего языка, соответствующим tm_mon,

2. Дни в неделе

У тебя есть:

int tm_wday;  // days since Sunday -- [0, 6]

а также %a, %A за strftime,

3. Часы в день

У тебя есть:

int tm_hour;  // hours since midnight -- [0, 23]

Есть также strftime спецификаторы, некоторые из которых чувствительны к текущей локали.

4. Минут в час

int tm_min;  // minutes after the hour -- [0, 59]

Также в этом случае вы получили некоторую помощь от нового C ++ 11 <chrono> библиотека:

std::cout << std::chrono::hours{1}/std::chrono::minutes{1} << '\n';

Это будет переносимо (и последовательно) выводить 60, Если ваш компилятор поддерживает constexpr и вы беспокоитесь об эффективности, эта величина может быть интегральной константой времени компиляции:

constexpr auto minutes_per_hour = std::chrono::hours{1}/std::chrono::minutes{1};

Тип minutes_per_hour гарантированно имеет целое число со знаком и не менее 29 бит.

5. Секунд в минуту

Спецификация C немного интересна на этом:

int tm_sec;  // seconds after the minutes -- [0, 60]

Диапазон не задокументирован как [0, 59] так, чтобы учесть добавление положительной високосной секунды. При этом ни одна ОС, о которой я знаю, на самом деле не обеспечивает точного учета високосных секунд. Все, кажется, следуют Unix Time который отслеживает UTC кроме игнорирования високосных секунд. Когда происходит дополнительная секунда, все ОС, о которых я знаю, просто воспринимают это как обычную коррекцию часов. Google классно воспринимает это как мазок исправлений за некоторое время.

Дополнительно вы можете последовательно и переносимо написать:

std::cout << std::chrono::minutes{1}/std::chrono::seconds{1} << '\n';

и получить 60,


Хотя это не определено стандартами C или C ++, каждая ОС, похоже, измеряет время с Новых 1970-х годов (пренебрегая високосными секундами). В C ++ 11 это количество доступно через:

auto tp = std::chrono::system_clock::now();

где tp будет иметь тип std::chrono::system_clock::time_point, это time_point имеет неопределенную точность (две недели, секунды, фемтосекунды и т. д.). Точность обнаруживается программно во время компиляции.


В случае, если это полезно, эта ссылка содержит код, который можно перевести tp в год / месяц / день час: минута: секунда и даже доли секунды (и наоборот). Ох, день недели, если вы тоже этого хотите (и несколько других календарных трюков). Этот код общественного достояния зависит от нестандартный но де-факто переносная эпоха Нового Года 1970 года. Она может быть легко перенесена в другие эпохи, если возникнет такая необходимость.

1

Другие решения

Я считаю, что я могу окончательно сказать, что есть не определение для любого из этих чисел в namespace std,

Я основываю это утверждение на том факте, что Boost’s gregorian.cpp жесткие коды все эти значения в get_value

Если у вас есть Boost, вы можете использовать get_value найти «Месяцы в году», «Дни в неделе» и «Часы в дне», выполнив:

locale::global(boost::locale::generator()(""));
cout.imbue(locale());

boost::locale::date_time now;

cout << "Months in a year: " << now.maximum(boost::locale::period::period_type(boost::locale::period::marks::month)) << endl;
cout << "Days in a week: " << now.maximum(boost::locale::period::period_type(boost::locale::period::marks::day_of_week)) << endl;
cout << "Hours in a day: " << now.maximum(boost::locale::period::period_type(boost::locale::period::marks::hour)) << endl;

Какие выводы:

Месяцев в году: 11
Дней в неделе: 7
Часов в день: 23

Обратите внимание на 0-месячные месяцы и часы и 1-дневные дни. Это согласуется с put_time«s %u флаг.

Если у вас нет Boost, вам нужно определить их самостоятельно.

Говард Хиннантрешение для поиска «минут в час» и «секунд в минуту» является на самом деле основан в определяет из namespace std:

cout << "Minutes in an hour: " << chrono::hours{1} / chrono::minutes{1} << endl;
cout << "Seconds in a minute: " << chrono::minutes{1} / chrono::seconds{1} << endl;

Какие выводы:

Минут через час: 60
Секунд в минуту: 60

0

По вопросам рекламы [email protected]