81.1. ПОДСИСТЕМА ВРЕМЕНИ




THIS SECTION IS UNDER CONSTRUCTION




Есть различные способы измерения времени. В настоящее время на нашей планете используются разные системы исчисления времени, но все они сходятся на том что у нас есть день, в котором есть часы, минуты секунды. Но с месяцами и годами все уже обстоит по другому. Григорианский календарь (от рождества Христова) Лунная Хиджра (арабский календарь) Восточные календари (масса вариантов). и еще куча других Как правило в компьютерном мире мы сталкиваемся с Григорианский календарем.


Календарь от Рождества Христова

1 день = 24 часа = 1440 минут = 86400 секунд 1 час = 60 минут = 3600 секунд 1 минута = 60 секунд 1 сек = 10^9 наносек 1 сек = 1000000 микросек 1 сек = 1000 миллисек Месяц. Количество дней в месяце зависит от его номера. Для февраля возможен дополнительный день в високосные года. Thirty days have September, April, June and November, And one day more, One year in four. Месяц кол-во дней January 31 February 28/29 March 31 April 30 May 31 June 30 July 31 August 31 September 30 October 31 November 30 December 31 Таким образов в году получается 365/366 дней Не каждый год является високосным: Не кратный 4 - простой кратный 4 - високосный Исключение - xx00 - если последние две цифры номера года нули - простой Исключение - xx00 - если последние две цифры номера года нули, и если часть номера года предшествующая двум последним цифрам делиться на 4 без остатка, то - високосный 2007 - простой 2006 - простой 2005 - простой 2004 - високосный 1896 - високосный 1900 - простой 1904 - високосный .... 1996 - високосный 2000 - високосный 2004 - високосный .... 2096 - високосный 2100 - простой 2104 - високосный 0 года не было был 1 год д.н.э 1 год н.э Поэтому начало нового тысячелетия было - 1 января 2001 года, а не 1 января 2000 года Коррекции календаря: Юлианский Грегорианский Юлианский календарь - христианская церковь 325 г н.э. Грегорианский был введен Oct 15, 1582 (это был Oct 5,1582 в Юлианском). Принимался Грегорианский календарь медленно: Великобритания 1752 Россия 1918 Греция 1923 Разница в том, что xx00 - всегда считались високосными в Юлианском календаре Сейчас разница уже - 13 дней (эта разница действует: с 1 марта 1900 до 29 фев 2100) Коперник родился 19 февраля 1473 года (естественно Юлианский календарь) для XV века разница 9 дней соответсвенно 19 + 9 = 28 февраля 1473 года по новому стилю.


Форматы представления

День недели Считаем по разному В России первый день недели - понедельник В Англоязычных странах - Sunday Форматы разные: 12.01.07 // RUS: DD.MM.YY 01/12/07 // US: MM/DD/YY 12/01/07 // UK: DD/MM/YY DD.MM.YYYY Russia YYYY.MM.DD Japan MM/DD/YYYY US DD/MM/YYYY UK и на время: 12:23:00 // RUS: HH:MM:SS.msec 23:10 12:03am // US: HH:MMLL 12-часовой, 24-часовой AM 0:00-11:59 PM 12:00-23:59 HTTP Cookies: Fri, 03 Dec 2010 ISO 8601 2010-12-03 T06:23:39-0500 RFC822 Fri, 03 Dec 2010 06:23:39 EST RFC850 Friday, 03-Dec-10 06:23:39 EST Номер недели в году Неделя A) ISO 8601:1988 та которая 4 дня общее правило - неделя на которой 4 или более дней принадлежит новому году - является его неделей номер 1 B) начинается с Sunday C) начинается с Monday начинается с 1 (1-53) # День недели сокращенно 0 Sunday Sun воскресение 1 Monday Mon понедельник 2 Tuesday Tue вторник 3 Wednesday Wed среда 4 Thursday Thu четверг 5 Friday Fri пятница 6 Saturday Sat суббота Days per month January 31 Январь February 28/29 Февраль March 31 Март April 30 Апрель May 31 Май June 30 Июнь July 31 Июль August 31 Август September 30 Сентябрь October 31 Октябрь November 30 Ноябрь December 31 Декабрь Advanced: Корректирующие секунды: 00:00:00 23:59:59 23:59:60 коректирующая секунда 23:59:61 тоже корректирующая секунда В любом случае из-за приливов вращение земли замедляется.


Time Zone

Time Zone Поясное время В Москве 15:00, в Петрапавловске-на-Камчатке полночь.





GMT Greenwich Mean Time EST Eastern Standart Time (GMT-5) US CST Central Standart Time (GMT-6) US MST Mountain Standart Time (GMT-7) US PST Pasific Standart Time (GMT-8) US HST Hawaiian Standart Time (GMT-10) US EST Eastern Standart Time (GMT+10) Австралия CST Central Standart Time (GMT+9:30) Австралия CET Centroeuropean time (GMT+1) вся западная европа кроме Португалии EET East European time (GMT+2) London GMT Moscow GMT+03 Los Angeles GMT-07 UTC = GMT без DST +-HHMM Секунды -12 -43200 -11 -39600 -10 -36000 -9 -32400 -8 -28800 -7 -25200 -6 -21600 -5 -18000 -4 -14400 -3.5 -12600 -3 -10800 0 0 1 3600 2 7200 3 10800 3.5 12600 4 14400 4.5 16200 5 18000 5.5 19800 5.75 20700 6 21600 6.5 23400 7 25200 8 28800 9 32400 9.5 34200 10 36000 12 43200 Линия перемены дат У нас в России есть 2 места - где сходяться сразу 3 timezone. Так решали вопрос - где покупать водку когда поздно. (Хотя населенных пунктов там нет). Летнее и зимнее время В целях экономии электроэнергии. Daylight Saving Time В разных странах переход на летнее время осуществляется в разное время Например MSK-LA разница в зависимости от даты может быть 11 или 12 часов. Переход на летнее время В 2 часа ночи - становиться 3 часа ночи Перевод на зимнее время: В 3 часа ночи - снова становиться 2 час ночи Россия: последнее воскресение марта (на 1 час вперед) последнее воскресение октября (на 1 час назад) США в 2005 принят новый закон о летнем времени вступил в силу с 2007 до 2007 - первое воскресение апреля c 2007 - на 3 недели раньше до 2007 - последнее воскресение октября с 2007 - первое воскресение ноября. Проблема наследования неделимого майората и близнецов Первый родился - 1:49 (до перевода времени) Второй рождился - 1:20 (после перевода времени) в один и тот же день когда переводили время Старшинство по нотариально заверенным показаниям акушерки. Время / \ UTC Локальное Как правило современные компьютеры имеют при инсталляции checkbox, который показывает что время в CMOS RTC настроено как локальное или как UTC. Для UTC нет зимнего и летнего времени (в отличии от GMT). NTFS хранит время в UTC. FAT хранит время - Local time. Современные OS имеют функцию автокорекции времени в CMOS RTC при переходе на/c летнее время (если RTC время стоит локальным). В случае нескольких OS на компьютере в результате их запуска происходит множественная коррекция времени. Конечно лучше всего иметь время в RTC как UTC.


Основные форматы времени

Основные форматы времени Связанны с OS и с дисковыми структурами и сетевыми пакетами DOS DOSDATE { unsigned DayOfMonth:5; // 1..31 unsigned MonthOfYear:4; // 1..12 unsigned Year:7; // 0..127 - means 1980..2107 } DOSTIME { unsigned SecondsDiv2:5; // 0..29 means 0..58 seconds unsigned Minutes:6; // 0..59 unsigned Hour:5; // 0..23 } Windows NT 64-битный тип показывающий время в 100ns интервалах начиная с 1 января 1601 года (UTC) typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME, UNIX struct timespec { time_t tv_sec; // количество секунд начиная с 00:00:00 1 Jan 1970 GMT long tv_nsec; } CDFS cdfs_time_date { char NumberOfYearSince1900; // 0..255 cover 1900..2255 char MonthOfYear; // 1..12 char DayOfMonth; // 1..31 char HourOfDay; // 0..23 char MinuteOfHour; // 0..59 char SecondOfMinute; // 0..59 char OffsetFromGreewich; // contain practically Timezone } UDF udf_timestamp { word TypeAndTimezone; word Year; // 0..65535 byte Month; // 1..12 byte Day; // 1..31 byte Hour; // 0..23 byte Minute; // 0..59 byte Second; // 0..59 byte CentiSeconds; // 0..99 byte HundredsOfms; // 0..99 byte Millisec; // 0..99 } Бывают и приватные форматы: например Microsoft VirtualPC VHD диски считают свой timestamp в секундах начиная с 00:00:00 1-Jan-2000.


Проблема 2000 года Y2K problem: Представление года в виде одного байта числом 91 - 1991 год 98 - 1998 год 00 - 2000 год, но в числовой форме - 00 < 91 - получаются ошибки. На самом деле самое страшное что нас ждет - это конец UNIX эпохи. Y2038 19 Jan 2038 3:14:07 UTC = 2147483647 sec on epoch 1-Jan-1970


Для работы требуется два вида времени Время / \ Календарное Интервальное Операционные системы для внутренних целей пользуются как правило интервальным временем с момента последней загрузки. Это основное время для внутренних синхронизаций - помому что календарное время может быть изменено (например изменена time zone, или летнее/зимнее). Так же есть определенные проблемы связанные с middleware - синхронизация времени между различными компьютерами. При небольших расхождениях бывают просто несколько убыстряют или замедляют отчет. Убыстряют - начинают обработчик вызывать чаще чем 1 раз в тик замедляют - не каждый тик


Времена: Реальное Время выполнения процесса/нити Как правило с этим временем связаны процессорные квоты для процесса/ниты. Монотонное системное время Как правило отсчитывается от момента запуска системы Синхронизационные события завязаны именно на него Оно никогда не уменьшается Коррекции времени как правило убыстряют или замедляют скорость изменения монотонного системного времени на некоторое время. Для разных задач требуются разные типы времен.


Источники времени: RTC (Real Time Clock) встоен во все компьютеры питается от батарейки, разрешающая способность - обычно не более 1/10 секунды. точность невысокая - бывают случае когда за год время уползает минут на 20 (особенно если батарейка совсем плохая). 2007 12 31 24:00:00 12 31/30/29/28 24 60 60 Проблемы: Имеет время обновления в процессе которого данные не consistance Timer - тоже есть во всех компьютерах - переодически дает прерывания, кроме того его можно прочитать. Прерывания обычно идут с частотой от 18.2 Hz, до 1000 Hz в зависимости от платформы и настроек. Обычно используется как основной источник для интервального времени операционной системы. В отличии от RTC как правило читается атомарно TSC (Time Stamp Counter) - в современных процессорах есть специальные регистры которые прибавляют к себе 1 каждый такт синхронизации. К сожалению это не панацея, потому что например при перегреве процессора он может понижать внутреннюю тактовую частоту - что отражается на скорости обновления счетчика.


Специальный случай - Watchdog Timer. Он работает следующим образом. После того как к нему было обращение он начинает отсчитывать интервал времени, как интервал закончен он выдает сигнал, который как правило завязан на сигнал RESET и осуществляет сброс машины. Это повышает надежность - если система зависла (т.е. не обращается определенное время к Watchdog timer), то ее сбрасывают аппаратно и она перезагружается.


Источники календарного времени: RTC Синхронизируем время с сервером по сети. Источники: Точные атомные часы Коллективные дисциплины: Коллективные дисциплины: 0 0 0 0 0 0 +2 -11 -3 +5 +8 +3 обрабытавают статистику, выбрасывают сильные отклонения. затем рассчитываем коррекцию


Какие вообще требования у программ к временным задержкам: 1) Schedule Надо что бы функция/программа вызвалась 1-Jan-2007 в 21:43:04 Как правило это делает специализированная программа - например croт демон Либо (если функция) то операционная система Точность как правило не очень важна. 1/10 секунды погоды не делает. 2) Interval Надо что бы функция вызвалась чераз 3.5 секунды Это делает операционная система, которой говорят Эта нить ждет объект таймера (а в объекте таймера уже стоит 3.5 cек вперед) 3) Micro Delay Мы работаем с оборудованием, и нам надо выждать маленькое количество времени (например 100ns, при этом если мы получим управление позже чем 200ns нам это тоже не поможет - поэтому нам не надо, что бы нас вытесняли. То есть работа происходит в той же нити.


Концептуальный RTL для работы со временем

По хорошему абсолютное время это пара Локальное время UTC время TimeZone 0 к которой хороше бы добавить (Daylight Saving) Yes/No чтобы избежать множественных коррекций Получить системное время Установить системное время (доп привелегии) Получить Timezone Установить Timezone (доп привелегии) Перевести абсолютное время в другую timezone из UTC в Local Time из Local Time в UTC (возможны варианты: в указанную time zone). Сравнить абсолютные времена (кто больше) Получить интервальное время из 2х абсолютных Форматный ввод/вывод времени т.е. преобразование даты/времени в строку и обратно Ждать указанное число времени (Вообще говоря деляться на 2 категории tick-based и speen-wait). Delay MicroDelay Получать сообщения с интервалом столько то времени Запустить Пауза/Продолжить Отменить Может быть разная семантика: например пока не вышел - новое сообщение не запускаем или запускаем или внутри всегда надо снова запускать. или автоматический перезапуск.


Реальные интерфейсы

UNIX ------------------------------------------------------------ sec usec nsec time_t timeval timespec ------------------------------------------------------------ Get time time gettimeofday clock_gettime Set time stime settimeofday clock_settime Sleep sleep select nanosleep Get ------------------------------------------------------------
//time.h

	typedef long time_t;

	struct	timespec
	{
		time_t		tv_sec;
		long		tv_nsec;
	};
                                
	struct	tm
	{
		int	tm_sec;
		int	tm_min;
		int	tm_hour;
		int	tm_mday;
		int	tm_mon;
		int	tm_year;
		int	tm_wday;
		int	tm_yday;
		int	tm_isdst;	// if daylight saving
	#ifdef	_BSD_SOURCE
		long	tm_gmtoff;
		const char*  tm_zone;
	#endif
	};


	time_t time(time_t* t);
	int    stime(time_t* t);

	clock_t	clock()		// process time


	int    clock_gettime(clockid_t clock_id,
	     		     struct timespec* ts); 

	int    clock_settime(clockid_t clock_id,
		             struct timespec ts);

	clockid_t:
		CLOCK_MONOTONIC
		CLOCK_PROCESS_CPUTIME_ID
		CLOCK_REALTIME
		CLOCK_THREAD_CPUTIME_ID

	char*	asctime(const struct tm* tm);
	char*	asctime_r(const struct tm* tm, char* buf);

	time_t	mktime(struct tm* tm);
	char*	ctime(const time_t* timep);
	char*   ctime_r(const time_t* timep, char* buf);

	struct tm * gmtime(const time_t* timep);                        // to UTC
	struct tm * gmtime_r(const time_t* timep, struct tm* result);

	struct tm * localtime(const time_t* timep);			// to local
	struct tm * localtime_r(const time_t* timep, struct tm * result);

	double	difftime(time_t time1, time_t time0);
			// in seconds


	"Tue Jun 17 23:17:28 1997\n\0"

	struct tm* getdate(const char* s);

	Non-standard:
	time_t	timegm(struct tm* tp);



	int	nanosleep(const struct timespec* req,
			  const struct timespec* rem);


	int	clock_nanosleep(clockid_t clock_id,		// POSIX
			int flags,
			const struct timespec* req,
			struct timespec* rem);


	size_t	strftime(char*s, size_t max, char* fmt, struct tm* tp);
							// printf analog

	%a	3-char name of weekday
	%A	full name of weekday
	%b 	3-char name of month
	%B	full name of month
	%c	preffered local expression of time or date (ctime()/asctime())
	%d	day of month (count from 0)
	%H	hour of day 24 hour mode
	%I	hour of day 12 hour mode
	%j	day of year (1..)
	%m	month (1..)
	%M	minute (0..)
	%p	AM or PM
	%S	seconds (0..)
	%U	week of year [week 1 start first Sunday of year]
	%W	week of year [week 1 start first Monday of year]	
	%w	day of week
	%x	local date expression
	%X	local time expression
	%y	last 2 digits of year
	%Y	full 4digit year
	%Z	standart abrv for time zone
	%%	%


	char*	strptime(char*s, char* fmt, struct tm* tp);	// scanf analog

Wide:
	wcsftime(wchar_t* buf,
		size_t bufsize,
		const wchar_t* format,
		const struct tm* tmbuf);


	wcsptime



struct timeval tv = { .tv_sec = 0, .tv_usec = 757 };
select(0, NULL, NULL, NULL);

	extern	int	daylight;
	extern	long	timezone;
	extern	day	*tzname[2];	// [0] = standart time
					// [1] = dst

	void	tzset(void);		// заполняет переменные.


//	TZ enviroment variable
//set TZ=EST5EDT
//	Eastern standart time
//	5 delta
//	EDT - in daylight time


	QNX
	time.h
	void	nsec2timespec(struct timespec* timespec_p, _uint64 nsec);
	_uint64	timespec2nsec(struct timespec* timespec_p);



//sys/time.h

	struct timeval
	{
		time_t		tv_sec;
		suseconds_t     tv_usec;
	};
	
	struct timezone
	{
		int		tz_minuteswest;
		int		tz_dsttime;	// DST correction
	};

	int gettimeofday(struct timeval* tv,
			 struct timezone* tz);

	int settimeofday(const struct timeval* tv,
			 const struct timezone* tz);

	int adjtime(const struct timeval* delta,
		    const struct timeval* olddelta);

	macroses:
		timerclear(struct timeval)
		timerisset(struct timeval)
		timercmp(struct timeval t0, struct timeval t1);
//sys/times.h

struct	tms
{
	clock_t	tms_utime;  	// user time
	clock_t	tms_stime;      // childs user time
	clock_t	tms_cutime;     // kernel time
	clock_t	tms_cstime;     // childs kernel time
};
//sys/timex.h

	int	adjtimex(struct timex* adj);

	struct timex!!!
//unistd.h

	unsigned int	sleep(unsigned int seconds);

	//BSD
	void	usleep(unsigned long usec);

	//SUS
	int	usleep(useconds_t usec);

BIOS DOS dos.h void _dos_getdate(struct dosdate_t* date); unsigned _dos_setdate(struct dosdate_t* date); void _dos_gettime(struct dostime_t* time); unsigned _dos_settime(struct dostime_t* time); struct dosdate_t { unsinged char day; unsigned char month; unsigned int year; unsigned char dayofweek; }; struct dostime_t { unsigned char hour; unsigned char minute; unsigned char second; unsigned char hsecond; }; Microsoft library char* _strtime(char* time); // hh:mm:ss

SYSTEMTIME

	VOID	GetSystemTime(LPSYSTEMTIME lpst)
		SetSystemTime
		GetLocalTime
	BOOL	SetLocalTime
	DWORD	GetTimeZoneInformation(LPTIME_ZONE_INFORMATION*)
		SetTimeZoneInformation


	typedef struct _SYSTEMTIME
	{
		WORD	wYear;
		WORD	wMonth;
		WORD	wDayOfWeek;
		WORD	wDay;
		WORD	wHour;
		WORD	wMinute;
		WORD	wSecond;
		WORD	wMilliseconds;
	} SYSTEMTIME, * LPSYSTEMTIME;


	typedef struct _TIME_ZONE_INFORMATION
	{
		LONG	Bias;
		TCHAR	StandardName[32];
		SYSTEMTIME  StandardDate;
		LONG	StandardBias;
		TCHAR	DaylightName[32];
		SYSTEMTIME  DaylightDate;
		LONG	DaylightBias;
	} TIME_ZONE_INFORMATION, * LPTIME_ZONE_INFORMATION;


Index Prev Next