A Unix idő két kódolási rétegből áll. Az első réteg egy időpontot skaláris valós számként kódol, amely az 1970. január 1., csütörtök 00:00:00 UTC óta eltelt másodpercek számát jelöli. A második réteg ezt a számot bitek vagy decimális számjegyek sorozataként kódolja.
A UTC-hez szokás szerint ez a cikk a napokat a Gergely-naptár szerint jelöli, és az egyes napokon belül órákban, percekben és másodpercekben számolja az időket. Néhány példa a Nemzetközi Atomidőt (TAI) is mutatja, egy másik időszámítási sémát, amely ugyanazokat a másodperceket használja és ugyanabban a formátumban jelenik meg, mint az UTC, de amelyben minden nap pontosan 86400 másodperc hosszú, fokozatosan elveszítve a szinkronizációt a Föld forgásával, évente nagyjából egy másodperc sebességgel.
Az idő számként való kódolásaSzerkesztés
Az Unix idő egyetlen előjeles szám, amely másodpercenként növekszik, így a számítógépek könnyebben tárolhatják és kezelhetik, mint a hagyományos dátumrendszereket. Az értelmező programok aztán át tudják alakítani ember által olvasható formátumba.
A Unix-korszak az 1970. január 1-jei 00:00:00 UTC időpont. Ezzel a definícióval van egy probléma, mivel az UTC a jelenlegi formájában 1972-ig nem létezett; ezt a kérdést alább tárgyaljuk. A rövidség kedvéért e szakasz további részében az ISO 8601 dátum- és időformátumot használjuk, amelyben a Unix-korszak 1970-01-01T00:00:00:00Z.
A Unix-időszám a Unix-korszakban nulla, és a korszak óta minden nap pontosan 86400-zal nő. Így 2004-09-16T00:00:00:00Z, 12677 nappal az epocha után, a Unix időszám 12677 × 86400 = 1095292800. Ez az epochától visszafelé is kiterjeszthető negatív számokkal; így az 1957-10-04T00:00:00:00Z, 4472 nappal az epocha előtt, a Unix-időszám -4472 × 86400 = -386380800. Ez napokon belül is érvényes; a nap bármely adott időpontjában az időszám az adott napot kezdő éjfél óta eltelt másodpercek száma, hozzáadva az adott éjfél időszámához.
Miatt, hogy a Unix-idő egy korszakon alapul, és azért a gyakori félreértés miatt, hogy a Unix-korszak az egyetlen korszak (gyakran “korszaknak” nevezik ), a Unix-időt néha korszakidőnek is nevezik.
SzökőmásodpercekSzerkesztés
A fenti séma azt jelenti, hogy egy normál UTC napon, amelynek időtartama 86400 másodperc, a Unix-időszám éjfélkor folyamatosan változik. Például a fenti példákban használt nap végén az időábrázolások a következőképpen alakulnak:
Ha szökőmásodperc következik be, az UTC-nap nem pontosan 86400 másodperc hosszú, és a Unix-időszám (amely mindig pontosan 86400-zal nő minden nap) megszakítást tapasztal. A szökőmásodpercek lehetnek pozitívak vagy negatívak. Negatív szökőmásodpercet még nem hirdettek ki, de ha mégis lenne, akkor a negatív szökőmásodpercű nap végén a Unix-időszám a következő nap kezdetére 1-gyel feljebb ugrana. Egy nap végén lévő pozitív szökőmásodperc alatt, ami átlagosan körülbelül másfél évente fordul elő, a Unix időszáma a szökőmásodperc alatt folyamatosan növekszik a következő napra, majd a szökőmásodperc végén visszaugrik 1-gyel (visszatérve a következő nap elejére). Például ez történt a szigorúan POSIX.1 szabványnak megfelelő rendszereken 1998 végén:
Az Unix időszámok a pozitív szökőmásodpercet közvetlenül követő másodpercben ismétlődnek. A 1483142400 Unix-időszám tehát kétértelmű: utalhat akár a szökőmásodperc kezdetére (2016-12-31 23:59:60), akár annak egy másodperccel későbbi végére (2017-01-01 00:00:00). Abban az elméleti esetben, amikor negatív szökőmásodperc fordul elő, nem keletkezik kétértelműség, hanem van egy olyan Unix-időszámtartomány, amely egyáltalán nem utal az UTC-idő egyetlen pontjára sem.
A Unix-órát gyakran a Network Time Protocolhoz (NTP) kapcsolódó, más típusú pozitív szökőmásodperc-kezeléssel valósítják meg. Ez olyan rendszert eredményez, amely nem felel meg a POSIX szabványnak. A részleteket lásd az NTP-re vonatkozó alábbi szakaszban.
Az UTC szökőmásodpercet nem tartalmazó időszakok kezelése esetén két Unix időszám közötti különbség megegyezik a megfelelő időpontok közötti időszak másodpercben kifejezett időtartamával. Ez egy elterjedt számítási technika. Ha azonban szökőmásodpercek fordulnak elő, az ilyen számítások rossz választ adnak. Azokban az alkalmazásokban, ahol ilyen szintű pontosságra van szükség, szükség van egy szökőmásodperc-táblázatra, amikor Unix-időkkel dolgozunk, és gyakran előnyösebb egy másik időkódolás használata, amely nem szenved ettől a problémától.
A Unix-időszám könnyen visszaalakítható UTC-idővé, ha a Unix-időszám hányadosát és modulusát vesszük, modulo 86400. A hányados az epocha óta eltelt napok száma, a modulus pedig az adott nap UTC éjféltől számított másodpercek száma. Ha olyan Unix-időszámot kapunk, amely egy pozitív szökőmásodperc miatt nem egyértelmű, ez az algoritmus úgy értelmezi, mint az éppen éjfél utáni időt. Soha nem generál olyan időt, amely szökőmásodperc alatt van. Ha olyan Unix-időszámot kapunk, amely negatív szökőmásodperc miatt érvénytelen, akkor ugyanilyen érvénytelen UTC-időt generál. Ha ezek a feltételek jelentősek, akkor a szökőmásodpercek felismeréséhez egy szökőmásodperc-táblázathoz kell fordulni.
Nem szinkron hálózati időprotokoll-alapú változatSzerkesztés
Gyakran egy Mills-stílusú Unix-órát valósítanak meg olyan szökőmásodperc-kezeléssel, amely nem szinkronban van a Unix-időszám változásával. Az időszám kezdetben ott csökken, ahol szökőmásodpercnek kellett volna bekövetkeznie, majd a szökőmásodperc után 1 másodperccel a helyes időre ugrik. Ez megkönnyíti a megvalósítást, és ezt írja le Mills tanulmánya. Ez történik egy pozitív szökőmásodpercen keresztül:
Ez megfelelően dekódolható, ha figyelmet fordítunk a szökőmásodperc állapotváltozóra, amely egyértelműen jelzi, hogy megtörtént-e már a szökés. Az állapotváltozó változása szinkronban van az ugrással.
Hasonló helyzet áll elő negatív szökőmásodperc esetén is, amikor a kihagyott másodperc kissé késik. Nagyon rövid ideig a rendszer egy névlegesen lehetetlen időszámot mutat, de ez a TIME_DEL állapotváltozóval felismerhető és korrigálható.
Egy ilyen típusú rendszerben a Unix időszám mindkét szökőmásodperc-típus körül sérti a POSIX-ot. A szökőmásodperc állapotváltozó összegyűjtése az időszámmal együtt lehetővé teszi az egyértelmű dekódolást, így igény esetén a helyes POSIX időszám generálható, vagy a teljes UTC idő tárolható egy megfelelőbb formátumban.
Az ilyen típusú Unix óra kezeléséhez szükséges dekódoló logika egy hipotetikus POSIX-konform órát is helyesen dekódolna, amely ugyanazt az interfészt használja. Ezt úgy érnénk el, hogy a TIME_INS állapotot jeleznénk egy beillesztett szökőmásodperc teljes időtartama alatt, majd a TIME_WAIT állapotot jeleznénk a következő másodperc teljes időtartama alatt, miközben megismételjük a másodpercek számlálását. Ehhez szinkron szökőmásodpercek kezelésére van szükség. Valószínűleg ez a legjobb módja annak, hogy az UTC-időt Unix-óra formájában, Unix-interfészen keresztül fejezzük ki, ha a mögöttes órát alapvetően nem zavarják a szökőmásodpercek.
TAI-alapú változatSzerkesztés
A Unix időszámítás egy másik, sokkal ritkább, nem konform változata a TAI kódolását jelenti UTC helyett; egyes Linux rendszerek így vannak beállítva. Mivel a TAI-ban nincsenek szökőmásodpercek, és minden TAI-nap pontosan 86400 másodperc hosszú, ez a kódolás valójában az 1970-01-01-01T00:00:00 TAI óta eltelt másodpercek tiszta lineáris számlálása. Ez sokkal egyszerűbbé teszi az időintervallum-aritmetikát. Az ilyen rendszerekből származó időértékek nem szenvednek olyan kétértelműségben, mint a szigorúan megfelelő POSIX-rendszerek vagy az NTP-vezérelt rendszerek.
Ezekben a rendszerekben a UTC és a pszeudo-Unix-idő ábrázolás közötti helyes konverzióhoz egy szökőmásodperc-táblázatot kell használni. Ez hasonlít ahhoz a módhoz, ahogyan az időzóna-táblákat kell megnézni a polgári időre és a polgári időre való átváltáshoz; az IANA időzóna-adatbázis tartalmazza a szökőmásodpercek adatait, és az ugyanebből a forrásból elérhető mintakód ezt az információt használja a TAI-alapú időbélyegek és a helyi idő közötti átváltáshoz. A konvertálás az UTC jelenlegi formájának 1972-es kezdete előtt (lásd alább az UTC-alap szakaszát) szintén definíciós problémákba ütközik.
Ez a TAI-alapú rendszer a felszíni hasonlóság ellenére nem Unix-idő. Az időket olyan értékekkel kódolja, amelyek több másodperccel eltérnek a POSIX időértékektől. Ennek a rendszernek egy változatát javasolták az ISO C time.h
-be való felvételre, de 2011-ben csak a UTC-részt fogadták el. A tai_clock
azonban létezik a C++20-ban.
A szám ábrázolásaSzerkesztés
A Unix időszám bármilyen számok ábrázolására alkalmas formában ábrázolható. Egyes alkalmazásokban a számot egyszerűen szövegesen, tizedesjegyek sorozataként ábrázolják, ami csak triviális további problémákat vet fel. A Unix-idők bizonyos bináris reprezentációi azonban különösen jelentősek.
Az időpontot reprezentáló Unix time_t
adattípus sok platformon egy előjeles egész szám, hagyományosan 32 bites (de lásd alább), amely közvetlenül kódolja a Unix-időszámot az előző szakaszban leírtak szerint. A 32 bit azt jelenti, hogy összesen körülbelül 136 évnyi tartományt fed le. A legkisebb ábrázolható dátum 1901-12-13 péntek, a legnagyobb ábrázolható dátum pedig 2038-01-19 kedd. Egy másodperccel 03:14:07 UTC 2038-01-19 után ez az ábrázolás túlcsordul. Ezt a mérföldkövet a szórakozás és a rettegés keverékével várjuk – lásd a 2038-as év problémáját.
Egyes újabb operációs rendszerekben az time_t
64 bitesre bővült. Ez mindkét irányban kb. 293 milliárd évvel bővíti az ábrázolható időket, ami irányonként több mint hússzorosa az univerzum jelenlegi korának.
Eredetileg vita volt arról, hogy a Unix time_t
előjeles vagy előjel nélküli legyen. Ha előjel nélküli, akkor a tartománya a jövőben megduplázódna, ami elhalasztaná a 32 bites túlcsordulást (68 évvel). Ezután azonban képtelen lenne a korszak előtti időpontok ábrázolására. A konszenzus szerint az time_t
előjeles, és ez a szokásos gyakorlat. A QNX operációs rendszer 6. verziójának szoftverfejlesztő platformja előjel nélküli 32 bites time_t
-t használ, bár a régebbi kiadásokban előjeles típust használtak.
A POSIX és az Open Group Unix specifikációk tartalmazzák a C szabványos könyvtárat, amely tartalmazza a <time.h>
fejlécfájlban definiált időtípusokat és függvényeket. Az ISO C szabvány kimondja, hogy az time_t
aritmetikai típusnak kell lennie, de nem ír elő semmilyen konkrét típust vagy kódolást számára. A POSIX megköveteli, hogy az time_t
egész szám típus legyen, de nem írja elő, hogy előjeles vagy előjel nélküli legyen.
A Unixban nincs hagyománya a nem egész számokat tartalmazó Unix időszámok bináris törtként való közvetlen ábrázolásának. Ehelyett a másodperc alatti pontosságú időket összetett adattípusokkal reprezentálják, amelyek két egész számból állnak, az első egy time_t
(a Unix idő integrális része), a második pedig az időszám tört része milliomodokban (struct timeval
-ban) vagy milliárdodokban (struct timespec
-ban). Ezek a struktúrák egy decimális alapú fixpontos adatformátumot biztosítanak, amely bizonyos alkalmazások számára hasznos, mások számára pedig triviálisan konvertálható.
UTC-alapSzerkesztés
A UTC jelenlegi formája, a szökőmásodpercekkel, csak 1972. január 1-jétől kezdődően van meghatározva. Ezt megelőzően, 1961. január 1-től létezett az UTC egy régebbi formája, amelyben nem csak alkalmi, nem egész számú másodperces időlépések voltak, hanem az UTC-szekundum is valamivel hosszabb volt, mint az SI-szekundum, és periodikusan változott, hogy folyamatosan közelítse a Föld forgását. 1961 előtt nem létezett UTC, és 1958 előtt nem volt széles körben elterjedt az atomi időmérés; ezekben a korszakokban a GMT valamilyen (közvetlenül a Föld forgásán alapuló) közelítését használták az atomi időskála helyett.
A Unix-idő pontos meghatározása az UTC kódolásaként csak akkor nem vitatható, ha az UTC jelenlegi formájára alkalmazzák. Az UTC ezen formájának kezdetét megelőző Unix-korszak nem befolyásolja a korszakban való használatát: az 1970. január 1. (Unix-korszak) és 1972. január 1. (az UTC kezdete) közötti napok száma nem kérdéses, és a napok száma az egyetlen, ami a Unix-idő szempontjából jelentős.
A +63072000 alatti (azaz 1972. január 1. előtti) Unix-időértékek jelentése nincs pontosan meghatározva. Az ilyen Unix-idők alapját leginkább úgy lehet értelmezni, hogy az UTC egy nem meghatározott közelítése. A korabeli számítógépek órái ritkán voltak elég pontosan beállítva ahhoz, hogy mindenképpen értelmes másodperc alatti időbélyegeket adjanak. A Unix-idő nem alkalmas az 1972 előtti idők ábrázolására a másodperc alatti pontosságot igénylő alkalmazásokban; az ilyen alkalmazásoknak legalább azt meg kell határozniuk, hogy az UT vagy a GMT melyik formáját használják.
2009 óta fontolgatják a szökőmásodpercek használatának megszüntetését a polgári időszámításban. E változás végrehajtásának egyik valószínű eszköze egy új, nemzetközi időnek nevezett időskála meghatározása, amely kezdetben megegyezik az UTC-vel, de ezt követően nem tartalmaz szökőmásodperceket, így a TAI-tól állandó eltolódással marad. Ha ez megtörténik, akkor valószínű, hogy a Unix-időt a jövőben az UTC helyett ezen új időskála alapján fogják meghatározni. A bizonytalanság, hogy ez bekövetkezik-e, nem teszi a jövőbeli Unix-időt kevésbé kiszámíthatóvá, mint amilyen már most is: ha az UTC-nek egyszerűen nem lennének további szökőmásodpercei, az eredmény ugyanaz lenne.