- 1 1. Sissejuhatus
- 2 2. Põhiteadmised aja käsitlemiseks C-keeles
- 3 3. Kuidas hankida praegune aeg
- 4 4. Aja vormindamine: strftime() kasutamine
- 5 5. Aja liitmine ja lahutamine
- 6 6. Valmistumine 2038. aasta probleemiks
- 7 7. Praktilised kasutusjuhud
- 8 8. Korduma kippuvad küsimused (KKK)
- 8.1 K1. Kuidas hankida praegune aeg Jaapani ajavööndis (JST)?
- 8.2 K2. Kas on võimalik hankida aega millisekundites?
- 8.3 K3. Kuidas käsitleda suveaega (DST)?
- 8.4 K4. Kas strftime() abil saab näidata nädalapäeva eesti keeles?
- 8.5 K5. Kuidas käsitleda aega pärast 2038. aastat?
- 8.6 K6. Miks programm ei kuva oodatud aega?
- 8.7 Kokkuvõte
- 9 9. Kokkuvõte
1. Sissejuhatus
C-keel on programmeerimiskeel, mida kasutatakse laialdaselt süsteemiprogrammeerimises ja manussüsteemides. Nende seas on “aja käsitlemine” paljudes programmides oluline element. Näiteks logisüsteem, mis kuvab praeguse aja, või taimeri funktsioon, mis käivitab määratud ajal kindla protsessi – mõlemad vajavad ajaga töötamist.
Selles artiklis selgitame peamiselt standardteeki time.h
, mida kasutatakse aja töötlemiseks C-keeles. Selle teegi abil saab hankida süsteemi praeguse aja, vormindada ja kuvada kellaaega. Lisaks käsitleme ka tuntud tulevast probleemi, mida nimetatakse „2038. aasta probleemiks“, et anda põhiteadmisi aja korrektsest käsitlemisest.
Artikkel on kirjutatud nii, et ka algajad mõistaksid seda, liikudes samm-sammult läbi põhimõistete ja praktiliste näidete. Lugedes õpid järgmisi teemasid:
- Põhiteadmised aja töötlemisest C-keeles
- Praeguse aja hankimine ja kuvamine
- Kellaaja vormindamine ja manipuleerimine
- Levinud probleemid ajaga töötamisel ja nende lahendused
Nende teadmiste abil saad rakendada aja töötlemist logimise, ajastamise ja taimerite juures. Järgmises jaotises vaatleme üksikasjalikult põhilisi andmetüüpe ja funktsioone, mida kasutatakse aja käsitlemisel C-keeles.
2. Põhiteadmised aja käsitlemiseks C-keeles
Aja töötlemiseks C-keeles kasutatakse standardteeki time.h
. See päisefail pakub andmetüüpe ja funktsioone süsteemiaja hankimiseks ja töötlemiseks. Siin selgitame üksikasjalikult vajalikke põhimõisteid aja käsitlemisel.
Mis on time.h?
time.h
on C-keele standardteek, mis toetab aja töötlemist. Selle abil saab hõlpsasti hankida süsteemi praeguse aja, vormindada ajandmeid ning teha liitmis- ja lahutustehted.
Peamised andmetüübid ja funktsioonid, mida kasutatakse:
- Andmetüübid:
time_t
,struct tm
- Funktsioonid:
time()
,localtime()
,strftime()
jne
Põhilised andmetüübid, mida kasutatakse aja töötlemisel
C-keeles aja käsitlemiseks on vaja mõista järgmisi andmetüüpe.
1. time_t
time_t
on andmetüüp süsteemiaja esitamiseks. See salvestab sekundite arvu, mis on möödunud alates 1. jaanuarist 1970 kell 00:00:00 (Unix epoch). See on kõige põhilisem tüüp, mida kasutatakse praeguse aja hankimisel programmis.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Hangi praegune aeg
printf("Praegune aeg sekundites: %ld\n", now);
return 0;
}
See kood kuvab süsteemi praeguse aja sekundites.
2. struct tm
struct tm
on struktuur, mida kasutatakse aja detailsemaks esitamiseks. See salvestab andmed nagu aasta, kuu, päev, tund, minut ja sekund.
Struktuuri liikmed
struct tm
sisaldab järgmisi liikmeid:
tm_sec
: sekundid (0–60)tm_min
: minutid (0–59)tm_hour
: tunnid (0–23)tm_mday
: kuupäev (1–31)tm_mon
: kuu (0–11, kus 0 = jaanuar)tm_year
: aastad alates 1900. aastasttm_wday
: nädalapäev (0–6, kus 0 = pühapäev)tm_yday
: aasta päev (0–365)tm_isdst
: suveaeg (1 = kehtib, 0 = ei kehti, -1 = teadmata)
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now); // Konverteeri lokaalaega
printf("Praegune kuupäev ja kellaaeg: %d-%02d-%02d %02d:%02d:%02d\n",
local->tm_year + 1900, // aasta aluseks on 1900
local->tm_mon + 1, // kuud algavad nullist
local->tm_mday,
local->tm_hour,
local->tm_min,
local->tm_sec);
return 0;
}
See kood kuvab praeguse kuupäeva ja kellaaja formaadis „AAAA-KK-PP TT:MM:SS“.
Muud andmetüübid aja mõõtmiseks
1. clock_t
clock_t
on andmetüüp protsessi käivitamise aja mõõtmiseks. Koos funktsiooniga clock()
saab mõõta koodi täitmise kestust.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
clock_t start, end;
double cpu_time_used;
start = clock();
// Kood, mille täitmise aega mõõdetakse
for (volatile long i = 0; i < 100000000; i++);
end = clock();
cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Täitmisaeg: %f sekundit\n", cpu_time_used);
return 0;
}
See kood mõõdab määratud tsükli täitmiseks kuluvat aega.
Andmetüüpide kokkuvõte
Allpool on tabel peamistest andmetüüpidest, mida kasutatakse aja käsitlemisel.
Andmetüüp | Selgitus | Põhiline kasutus |
---|---|---|
time_t | Süsteemiaja hoidmine (sekundites) | Praeguse aja hankimine |
struct tm | Detailne aja info (aasta, kuu, päev, tund, minut, sekund) | Aja vormindamine ja manipuleerimine |
clock_t | Protsessi täitmisaeg | Täitmise kestuse mõõtmine |
3. Kuidas hankida praegune aeg
C-keeles saab praegust aega hankida time.h
päisefaili kaudu pakutava funktsiooniga time()
. Selles jaotises selgitame põhilist kasutust ning teisendamist lokaalseks ajaks või UTC-ajaks.
Praeguse aja hankimise põhitõed
Funktsioon time()
time()
tagastab süsteemiaja väärtuse time_t
tüübis. See funktsioon on väga lihtne: piisab NULL
argumendist, et hankida praegune aeg.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Hangi praegune aeg
printf("Praegune aeg (sekundites): %ld\n", now);
return 0;
}
Väljundi näide
Praegune aeg (sekundites): 1700000000
Aja teisendamine inimesele loetavasse vormi
Teisendamine lokaalseks ajaks: localtime()
Funktsioon localtime()
teisendab time_t
väärtuse lokaalse ajavööndi alusel struct tm
struktuuriks.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Hangi praegune aeg
struct tm *local = localtime(&now); // Teisenda lokaalseks ajaks
printf("Praegune kohalik aeg: %d-%02d-%02d %02d:%02d:%02d\n",
local->tm_year + 1900, // aasta aluseks on 1900
local->tm_mon + 1, // kuud algavad nullist
local->tm_mday,
local->tm_hour,
local->tm_min,
local->tm_sec);
return 0;
}
Väljundi näide
Praegune kohalik aeg: 2025-01-12 15:30:45
Teisendamine UTC-ajaks: gmtime()
Funktsioon gmtime()
teisendab time_t
väärtuse universaalseks ajaks (UTC) vastavalt struct tm
struktuuri.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Hangi praegune aeg
struct tm *utc = gmtime(&now); // Teisenda UTC-ajaks
printf("Praegune UTC aeg: %d-%02d-%02d %02d:%02d:%02d\n",
utc->tm_year + 1900,
utc->tm_mon + 1,
utc->tm_mday,
utc->tm_hour,
utc->tm_min,
utc->tm_sec);
return 0;
}
Väljundi näide
Praegune UTC aeg: 2025-01-12 06:30:45
UTC ja kohaliku aja erinevus
- UTC (Koordineeritud maailmaaeg)
On maailma standardaeg, mille järgi määratakse kõik ajavööndid. - Kohalik aeg
On süsteemi ajavööndi seadete järgi kohandatud aeg.
Näiteks Jaapani standardaeg (JST) on UTC+9 tundi. Seetõttu on localtime()
ja gmtime()
väljundite vahel 9-tunnine erinevus.
Praeguse aja kuvamine stringina
Funktsioon ctime()
ctime()
on lihtne funktsioon, mis kuvab time_t
väärtuse otse stringina.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
printf("Praegune aeg: %s", ctime(&now)); // Kuva aeg stringina
return 0;
}
Väljundi näide
Praegune aeg: Sat Jan 12 15:30:45 2025
Tähtis märkus
- Väljund on alati inglise keeles.
- Kui on vaja paindlikumat vormingut, kasuta funktsiooni
strftime()
(selgitatakse järgmises jaotises).
Kokkuvõte
- Praeguse aja hankimiseks kasuta funktsiooni
time()
. - Kohalik aeg teisendatakse funktsiooniga
localtime()
, UTC-aeg funktsioonigagmtime()
. - Lihtsaks stringi kuvamiseks kasuta funktsiooni
ctime()
.
4. Aja vormindamine: strftime()
kasutamine
Kui soovid C-keeles kuupäeva ja kellaaja kuvada inimesele loetaval kujul, siis strftime()
funktsioon võimaldab määrata paindlikud vormingud. Selle abil saab lisaks aastale, kuule, päevale, tunnile, minutile ja sekundile näidata ka näiteks nädalapäeva või aasta järjestikust päeva.
Selles jaotises tutvustame strftime()
funktsiooni põhilist kasutust ja kasulikke näiteid.
Mis on strftime() funktsioon?
strftime()
teisendab struct tm
andmed stringiks vastavalt määratud vormingu spetsifikaatoritele.
Funktsiooni prototüüp
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
s
: puhver, kuhu salvestatakse vormindatud string.max
: puhvri maksimaalne suurus.format
: vormingu spetsifikaatorid.tm
:struct tm
, mida vormindatakse.
Tagastusväärtus
Tagastab teisendatud stringi pikkuse baitides. Kui tekib viga, tagastatakse 0.
Põhiline kasutus
Allpool on näide, kuidas kuvada praegune aeg kujul „AAAA-KK-PP TT:MM:SS“.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Hangi praegune aeg
struct tm *local = localtime(&now); // Teisenda lokaalseks ajaks
char buffer[80]; // Puhver vormindatud stringi jaoks
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local);
printf("Vormindatud aeg: %s\n", buffer);
return 0;
}
Väljundi näide
Vormindatud aeg: 2025-01-12 15:30:45
Levinud vormingu spetsifikaatorid
Spetsifikaator | Selgitus | Näide väljundist |
---|---|---|
%Y | Aasta (4 numbrit) | 2025 |
%m | Kuu (01–12) | 01 |
%d | Päev (01–31) | 12 |
%H | Tund (00–23) | 15 |
%M | Minutid (00–59) | 30 |
%S | Sekundid (00–60) | 45 |
%A | Nädalapäev (täisnimi, inglise keeles) | Laupäev |
%a | Nädalapäev (lühendatud, inglise keeles) | Sat |
%j | Aasta järjestikune päev (001–366) | 012 |
%p | AM või PM (sõltub lokaalist) | PM |
Näide
- Vorming:
"%A, %d %B %Y"
- Väljund:
Laupäev, 12 Jaanuar 2025
Praktilised näited: kohandatud vormingud
1. Jaapani stiilis kuupäev
Jaapanis kasutatakse sageli vormi „AAAA年KK月PP日 TT時MM分SS秒“.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now);
char buffer[80];
strftime(buffer, sizeof(buffer), "%Y年%m月%d日 %H時%M分%S秒", local);
printf("Praegune aeg: %s\n", buffer);
return 0;
}
Väljundi näide
Praegune aeg: 2025年01月12日 15時30分45秒
2. Logifailide ajatempli loomine
Süsteemilogides kasutatakse sageli vormingut „AAAA-KK-PP_TT-MM-SS“.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now);
char buffer[80];
strftime(buffer, sizeof(buffer), "%Y-%m-%d_%H-%M-%S", local);
printf("Logi ajatemper: %s\n", buffer);
return 0;
}
Väljundi näide
Logi ajatemper: 2025-01-12_15-30-45
3. Vorming ingliskeelse nädalapäevaga
Genereerib näiteks kuju „Sat, 12 Jan 2025“.
Näide kasutusest
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now);
char buffer[80];
strftime(buffer, sizeof(buffer), "%a, %d %b %Y", local);
printf("Inglise vorming: %s\n", buffer);
return 0;
}
Väljundi näide
Inglise vorming: Sat, 12 Jan 2025
4. Vigade käsitlemine
Kui strftime()
tagastab 0, võib põhjuseks olla liiga väike puhver või vale vorming. Kontrolli:
- Kas puhvri suurus (
sizeof(buffer)
) on piisav. - Kas vormingu spetsifikaatorid on õiged.
Kokkuvõte
strftime()
võimaldab paindlikult vormindada kuupäeva ja kellaaega. Seda saab kasutada logifailide ajatempli loomiseks või inimesele loetava kuupäeva kuvamiseks.
Järgmises jaotises vaatleme, kuidas aega liita ja lahutada – näiteks lisada 1 tund praegusele ajale või arvutada järgmise päeva kuupäev.
5. Aja liitmine ja lahutamine
C-keeles saab aega manipuleerida (liita või lahutada), et arvutada tulevasi või möödunud ajapunkte. Selles jaotises selgitame, kuidas kasutada time_t
tüüpi ja funktsiooni mktime()
aja arvutamiseks.
Aja liitmise ja lahutamise põhimõte
time_t
tüüp esitab süsteemiaega sekundites, seega on võimalik teha lihtsaid arvutusi sekundite kaupa.
- Liitmine: lisa sekundite arv, et arvutada tulevane aeg.
- Lahutamine: lahuta sekundite arv, et arvutada möödunud aeg.
Kuidas aega manipuleerida
1. Otsene manipuleerimine time_t
-ga
time_t
väärtusele saab otseselt lisada või lahutada sekundeid.
Näide: ühe tunni võrra edasi
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Praegune aeg
time_t future = now + (60 * 60); // 1 tund hiljem (60 minutit × 60 sekundit)
printf("Praegune aeg (sekundites): %ld\n", now);
printf("1 tund hiljem (sekundites): %ld\n", future);
return 0;
}
Väljundi näide
Praegune aeg (sekundites): 1700000000
1 tund hiljem (sekundites): 1700003600
See meetod sobib lihtsate sekundipõhiste arvutuste jaoks.
2. Manipuleerimine mktime()
-i abil
mktime()
võimaldab arvutada keerukamaid kuupäeva- ja ajaoperatsioone (nt järgmine päev või järgmine kuu).
Näide: järgmise päeva aja arvutamine
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Praegune aeg
struct tm *local = localtime(&now); // Teisenda lokaalseks ajaks
local->tm_mday += 1; // Liigu ühe päeva võrra edasi
time_t tomorrow = mktime(local); // Konverteeri tagasi time_t-ks
printf("Praegune aeg: %s", ctime(&now));
printf("Homme: %s", ctime(&tomorrow));
return 0;
}
Väljundi näide
Praegune aeg: Sat Jan 12 15:30:45 2025
Homme: Sun Jan 13 15:30:45 2025
Märkus
mktime()
korrigeerib automaatselt kuupäeva (nt 31. jaanuar + 1 päev = 1. veebruar).
Aja erinevuse arvutamine: difftime()
Kahe time_t
väärtuse erinevust saab arvutada funktsiooniga difftime()
. See tagastab sekundite arvu.
Näide: kahe aja vahe
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL); // Praegune aeg
time_t future = now + (60 * 60 * 24); // 1 päev hiljem
double diff = difftime(future, now); // Arvuta vahe
printf("Praegune aeg: %s", ctime(&now));
printf("1 päev hiljem: %s", ctime(&future));
printf("Erinevus: %.0f sekundit\n", diff);
return 0;
}
Väljundi näide
Praegune aeg: Sat Jan 12 15:30:45 2025
1 päev hiljem: Sun Jan 13 15:30:45 2025
Erinevus: 86400 sekundit
Aja manipuleerimise praktilised näited
1. Sündmuste ajastamine
Arvuta tulevane aeg ja käivita sündmused kindla intervalliga.
2. Ajalooliste andmete analüüs
Arvuta möödunud ajad, et filtreerida või analüüsida logisid või andmeid.
3. Tingimuslik käitumine kellaaja alusel
Võrdle praegust aega kindla võrdlusajaga ja muuda programmi loogikat vastavalt.
Olulised märkused
- Ajavööndid: lokaalse aja puhul arvesta ajavööndi seadeid. Rahvusvahelistes rakendustes on soovitatav kasutada UTC-aega.
- Liitmise ja lahutamise ühikud: sekundeid kasutatakse lihtsate arvutuste jaoks, kuid suuremate arvutuste puhul on parem kasutada
struct tm
-i.
Kokkuvõte
time_t
võimaldab lihtsat liitmist ja lahutamist sekundite kaupa.- Keerulisemate arvutuste jaoks kasuta funktsiooni
mktime()
. - Aja erinevuse arvutamiseks kasuta funktsiooni
difftime()
.
Järgmises jaotises käsitleme C-keele ajakäsitlusega seotud 2038. aasta probleemi, et valmistuda tulevaste süsteemide arendamiseks.
6. Valmistumine 2038. aasta probleemiks
C-keeles kasutatakse laialdaselt time_t
tüüpi süsteemiaja esitamiseks. Kuid selle tüübiga on seotud suur probleem, mida tuntakse kui „2038. aasta probleem“. Selles jaotises selgitame selle probleemi põhjuseid, mõjusid ja lahendusi.
Mis on 2038. aasta probleem?
2038. aasta probleem tekib, kuna paljud süsteemid, sealhulgas C-keel, kasutavad time_t
tüüpi.
Põhjused
time_t
on tavaliselt implementeeritud 32-bitise allkirjaga täisarvuna.- See salvestab sekundid alates 1. jaanuarist 1970 kell 00:00:00 (Unix epoch).
- 32-bitine täisarv võib esitada maksimaalselt 2,147,483,647 väärtust.
- See piir saavutatakse 19. jaanuaril 2038 kell 03:14:07 (UTC), mille järel toimub ületäitumine ning väärtus muutub negatiivseks.
Näide
#include <stdio.h>
#include <time.h>
int main() {
time_t max_time = 2147483647; // Maksimaalne väärtus
printf("2038. aasta piiraeg: %s", ctime(&max_time));
time_t overflow_time = max_time + 1; // Ületäitumine
printf("Ületäitumise järel: %s", ctime(&overflow_time));
return 0;
}
Väljundi näide
2038. aasta piiraeg: Tue Jan 19 03:14:07 2038
Ületäitumise järel: Fri Dec 13 20:45:52 1901
Selles näites ajaväärtus „keritakse tagasi“ aastasse 1901.
2038. aasta probleemi mõju
See probleem võib mõjutada paljusid süsteeme:
- Pikaajalised taimerid ja ajastamised
- Pärast 2038. aastat ei tööta ajapõhised taimerid ja ajastamised õigesti.
- Failisüsteemid
- Failide ajatemplid (loomis- või muutmisajad) võivad muutuda valeks.
- Võrgusüsteemid
- Autentimine ja logid, mis sõltuvad ajast, võivad anda vigu.
- Manussüsteemid
- Vanemad seadmed ja infrastruktuur (nt ATM-id või POS-terminalid) võivad jääda ilma parandusteta.
Lahendused 2038. aasta probleemile
Probleemi vältimiseks saab rakendada järgmisi lähenemisi:
1. Üleminek 64-bitisele keskkonnale
- Määratle
time_t
64-bitise täisarvuna – see kõrvaldab praktiliselt probleemi. - 64-bitine
time_t
suudab esitada aega umbes 292 miljardit aastat.
Näide
Paljudes 64-bitistes keskkondades on probleem juba lahendatud vaikimisi.
2. Väliste teekide kasutamine
- Võid kasutada paindlikumaid teeke nagu
Boost.DateTime
võiChrono
.
3. Alternatiivsed ajavormingud
- Kasuta stringe või kohandatud andmetüüpe. See on keerukam ja nõuab süsteemi ümberkujundamist.
Praktilised sammud
Serverite uuendamine
- Kui kasutatakse 32-bitiseid süsteeme, tuleks need uuendada 64-bitistele OS-idele ja teekidele.
Olemasoleva koodi ülevaatus
- Kontrolli, kus kasutatakse
time_t
-d, ja hinda ületäitumise riske.
Uute projektide arendamine
- Soovitatav on arvestada vaikimisi 64-bitist ajakeskkonda.
Praegune olukord
Tänapäeval on paljud süsteemid juba üle läinud 64-bitisele keskkonnale, mistõttu uute projektide puhul probleem enamasti ei teki. Kuid vanemates manussüsteemides võib see endiselt eksisteerida.
Kokkuvõte
- 2038. aasta probleem tekib, kui
time_t
on 32-bitine. - Parimad lahendused on 64-bitisele keskkonnale üleminek või kaasaegsete teekide kasutamine.
- Vanemate süsteemide puhul tuleks varakult võtta tarvitusele abinõud.
Järgmises jaotises tutvustame praktilisi kasutusjuhtumeid, kus C-keeles ajaga töötamist rakendatakse päris süsteemides – näiteks logide ajatempleid ja sündmuste ajastamist.
7. Praktilised kasutusjuhud
C-keele ajafunktsioonid ei piirdu ainult praeguse aja hankimisega, vaid neid saab kasutada ka paljudes praktilistes süsteemides. Selles jaotises vaatleme mõningaid näiteid, kuidas ajakäsitlust kasutada reaalsetes olukordades. Need annavad ideid, kuidas oma programmi täiustada.
1. Ajatempli lisamine logidele
Süsteemi- ja vealogidesse lisatakse tavaliselt ajatempleid, et hiljem oleks lihtsam jälgida probleemide põhjuseid.
Näide: logi ajatempli salvestamine
#include <stdio.h>
#include <time.h>
void log_message(const char *message) {
time_t now = time(NULL);
struct tm *local = localtime(&now);
char timestamp[80];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", local);
printf("[%s] %s\n", timestamp, message);
}
int main() {
log_message("Programm käivitati");
log_message("Tekkis viga");
log_message("Programm lõpetati");
return 0;
}
Väljundi näide
[2025-01-12 15:30:45] Programm käivitati
[2025-01-12 15:30:46] Tekkis viga
[2025-01-12 15:30:47] Programm lõpetati
2. Sündmuste ajastamine
Kindla intervalliga toimingute käivitamine (nt iga 5 sekundi järel) on levinud mängudes või reaalajasüsteemides.
Näide: taimeri rakendamine
#include <stdio.h>
#include <time.h>
#include <unistd.h> // sleep() UNIX süsteemides
void perform_task() {
printf("Sündmus käivitati\n");
}
int main() {
time_t start = time(NULL);
while (1) {
time_t now = time(NULL);
if (difftime(now, start) >= 5) { // iga 5 sekundi järel
perform_task();
start = now;
}
sleep(1); // vähenda CPU koormust
}
return 0;
}
Väljundi näide
Sündmus käivitati
(5 sekundi pärast)
Sündmus käivitati
(veel 5 sekundi pärast)
Sündmus käivitati
3. Tähtaegade haldamine
Kuupäeva arvutamist kasutatakse näiteks maksetähtaegade või tööde tähtaegade jälgimiseks.
Näide: maksetähtaja arvutamine
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *due_date = localtime(&now);
due_date->tm_mday += 30; // 30 päeva hiljem
mktime(due_date); // normaliseeri kuupäev
char buffer[80];
strftime(buffer, sizeof(buffer), "%Y-%m-%d", due_date);
printf("Maksetähtaeg on: %s\n", buffer);
return 0;
}
Väljundi näide
Maksetähtaeg on: 2025-02-11
4. Programmi täitmise aja mõõtmine
Optimeerimisel on oluline mõõta koodi täitmise kestust.
Näide: täitmisaja mõõtmine
#include <stdio.h>
#include <time.h>
int main() {
clock_t start = clock();
// Näidiskood (tsükkel)
for (volatile long i = 0; i < 100000000; i++);
clock_t end = clock();
double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("Täitmisaeg: %.3f sekundit\n", elapsed);
return 0;
}
Väljundi näide
Täitmisaeg: 0.215 sekundit
5. Tingimuslik loogika kellaaja alusel
Programmi käitumist saab muuta sõltuvalt kellaajast (nt hommik vs pärastlõuna).
Näide: sõnum hommikul ja pärastlõunal
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now);
if (local->tm_hour < 12) {
printf("Tere hommikust!\n");
} else {
printf("Tere päevast!\n");
}
return 0;
}
Väljundi näide (hommikul)
Tere hommikust!
Väljundi näide (pärastlõunal)
Tere päevast!
Kokkuvõte
C-keele ajakäsitlus on kasulik logide, ajastamiste, kuupäevade arvutamise ja täitmisaja mõõtmise puhul. Need praktilised näited on abiks igapäevaste programmide kirjutamisel.
Järgmises jaotises käsitleme Korduma kippuvaid küsimusi (KKK), et vastata lugejate sagedastele kahtlustele.
8. Korduma kippuvad küsimused (KKK)
C-keeles aja töötlemisel tekib algajatel ja ka edasijõudnutel sageli küsimusi. Selles jaotises vastame levinud küsimustele, et süvendada arusaamist ajaga töötamisest.
K1. Kuidas hankida praegune aeg Jaapani ajavööndis (JST)?
V. Jaapani standardaeg (JST) on 9 tundi ees UTC-st. Funktsioon localtime()
arvestab süsteemi ajavööndi seadistust, seega kui süsteem on seadistatud JST ajavööndile, tagastatakse aeg automaatselt Jaapani ajana.
Näide
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now);
printf("Praegune Jaapani aeg: %d-%02d-%02d %02d:%02d:%02d\n",
local->tm_year + 1900, local->tm_mon + 1, local->tm_mday,
local->tm_hour, local->tm_min, local->tm_sec);
return 0;
}
Märkus: veendu, et süsteemi ajavöönd on õigesti seadistatud.
K2. Kas on võimalik hankida aega millisekundites?
V. Standardne time.h
ei toeta millisekundite hankimist. Kuid platvormipõhiste API-de abil (nt UNIX-is funktsioon gettimeofday()
) saab millisekundi täpsuse.
Näide: millisekundite hankimine UNIX-is
#include <stdio.h>
#include <sys/time.h>
int main() {
struct timeval tv;
gettimeofday(&tv, NULL);
printf("Praegune aeg: %ld sekundit ja %ld millisekundit\n",
tv.tv_sec, tv.tv_usec / 1000);
return 0;
}
Väljundi näide
Praegune aeg: 1700000000 sekundit ja 123 millisekundit
K3. Kuidas käsitleda suveaega (DST)?
V. Suveaja (Daylight Saving Time, DST) infot saab struct tm
liikmest tm_isdst
.
1
: suveaeg on aktiivne.0
: suveaeg ei kehti.-1
: info pole saadaval.
Näide
#include <stdio.h>
#include <time.h>
int main() {
time_t now = time(NULL);
struct tm *local = localtime(&now);
if (local->tm_isdst > 0) {
printf("Hetkel kehtib suveaeg\n");
} else {
printf("Hetkel ei kehti suveaeg\n");
}
return 0;
}
K4. Kas strftime()
abil saab näidata nädalapäeva eesti keeles?
V. strftime()
arvestab lokaadi (keel ja piirkond). Funktsiooniga setlocale()
saab määrata keeleks eesti keele, et näidata nädalapäeva eesti keeles.
Näide
#include <stdio.h>
#include <time.h>
#include <locale.h>
int main() {
setlocale(LC_TIME, "et_EE.UTF-8");
time_t now = time(NULL);
struct tm *local = localtime(&now);
char buffer[80];
strftime(buffer, sizeof(buffer), "%Y. aasta %d. %B, %A", local);
printf("Praegune kuupäev: %s\n", buffer);
return 0;
}
Väljundi näide
Praegune kuupäev: 2025. aasta 12. jaanuar, pühapäev
Märkus: see sõltub, kas eesti lokaadid on süsteemi installitud.
K5. Kuidas käsitleda aega pärast 2038. aastat?
V. Probleemi vältimiseks kasuta 64-bitist time_t
või alternatiivseid andmetüüpe. 64-bitistes süsteemides töötab time_t
juba suuremate väärtustega.
Näide: 64-bitine time_t
#include <stdio.h>
#include <time.h>
int main() {
time_t future = 2147483648; // väärtus üle 2038. aasta piiri
printf("Aeg: %s", ctime(&future));
return 0;
}
Väljundi näide
Aeg: Tue Jan 19 03:14:08 2038
Märkus: 32-bitises süsteemis ei pruugi see toimida.
K6. Miks programm ei kuva oodatud aega?
Peamised põhjused võivad olla:
- Vale ajavöönd: kontrolli süsteemi ajavööndi seadistust.
- Vigased väärtused struktuuris
tm
: kuimktime()
teisendab vigase väärtuse, võib tulemus olla vale. - Vananenud teegid: süsteemi ajateegid võivad vajada uuendamist.
Kokkuvõte
Selles KKK-jaotises vastasime levinud küsimustele C-keele ajafunktsioonide kohta. Katsetades koodinäiteid, saad paremini aru aja töötlemisest.
Järgmises jaotises võtame kogu artikli kokku ja kordame üle peamised punktid.
9. Kokkuvõte
Selles artiklis käsitlesime C-keele ajafunktsioone alates põhiteadmistest kuni praktiliste rakendusteni. Aja töötlemine on programmide üks olulisemaid funktsioone ja selle korrektne mõistmine võimaldab seda kasutada paljudes olukordades.
Õpitu kordamine
Peamised punktid, mida selles artiklis käsitlesime:
- Aja töötlemise alused C-keeles
- Õppisime, kuidas kasutada
time.h
päisefaili süsteemiaja hankimiseks ja erinevateks operatsioonideks. - Tutvusime peamiste andmetüüpide (
time_t
,struct tm
) ja funktsioonidega (time()
,localtime()
,mktime()
jne).
- Praeguse aja hankimine ja kuvamine
- Kasutasime funktsiooni
time()
aja hankimiseks ning teisendasime seda lokaalseks ajaks ja UTC-ks. - Kuvamiseks kasutasime
ctime()
jastrftime()
, et muuta aeg inimesele loetavaks.
- Aja manipuleerimine ja arvutamine
- Õppisime, kuidas liita ja lahutada aega sekundite kaupa
time_t
abil. - Kasutades
mktime()
, saime arvutada üle kuupäevade ja aegade. difftime()
abil arvutasime kahe aja erinevust.
- 2038. aasta probleemi mõistmine ja lahendamine
- Selgitasime, kuidas 32-bitine
time_t
tekitab probleeme pärast 2038. aastat. - Pakkusime lahendusi, sealhulgas 64-bitise keskkonna kasutamist ja sobivate teekide rakendamist.
- Praktilised kasutusjuhud
- Nägime näiteid logide ajatemplitest, sündmuste ajastamisest, tähtaegade arvutamisest ja täitmisaja mõõtmisest.
- KKK abil lahendasime levinud küsimused
- Arutasime Jaapani aja hankimist, millisekundite täpsust, suveaja arvestamist ja 2038. aasta järgselt töötamist.
Järgmised sammud
Kui soovid teemat süvitsi uurida, soovitame:
- Aja töötlemine mitmelõimelistes keskkondades – et tagada lõimes turvalised operatsioonid.
- Väliste teekide kasutamine – näiteks Boost või Chrono teek paindlikumate funktsioonide jaoks.
- Ajavööndite haldus – globaalses süsteemis on ajavööndite korrektne käsitlemine hädavajalik.
Lõppsõna
Aeg on iga programmi oluline element. Loodame, et see artikkel aitas sul paremini mõista C-keele ajafunktsioone ja annab tugeva aluse tõhusamate programmide loomiseks.