Go’da sana va vaqt bilan ishlash
Go’da sana, vaqt va vaqt oralig‘i bilan ishlash uchun standart kutubxonadagi time paketi ishlatiladi. Backend API’da yozuv yaratilgan vaqtni saqlash, token muddatini tekshirish, vazifaga timeout qo‘yish va foydalanuvchi vaqt zonasida sanani ko‘rsatish shu paketning keng tarqalgan vazifalaridir.
Vaqt bilan ishlashda uch tushunchani ajratish muhim:
time.Time— vaqt chizig‘idagi muayyan nuqta;time.Duration— ikki hodisa orasidagi davomiylik;time.Location— vaqt nuqtasini qaysi vaqt zonasi qoidalari bilan ko‘rsatish kerakligi.
Masalan, bitta uchrashuv Toshkentda 14:00, Londonda boshqa mahalliy soatda ko‘rinishi mumkin. Vaqt nuqtasi bitta, uni ko‘rsatish zonasi esa turlicha.
Joriy vaqtni olish
time.Now() operatsion tizimdan joriy vaqtni olib, time.Time qiymatini qaytaradi:
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println("Mahalliy vaqt:", now)
fmt.Println("UTC vaqti:", now.UTC())
}
Natija dastur qachon va qaysi muhitda ishga tushirilganiga bog‘liq. Masalan:
Mahalliy vaqt: 2026-03-15 14:30:20.123456789 +0500 +05 m=+0.000031201
UTC vaqti: 2026-03-15 09:30:20.123456789 +0000 UTC
time.Now() natijasi serverning mahalliy vaqt zonasidan foydalanadi. Server UTCda sozlangan bo‘lsa, birinchi satr ham UTCda chiqadi. Kodni ma’lum zona deb taxmin qilish o‘rniga kerakli zonani ochiq ko‘rsating.
Standart matn ko‘rinishidagi qismlar:
| Qism | Ma’nosi |
|---|---|
2026-03-15 |
yil, oy va kun |
14:30:20.123456789 |
soat, daqiqa, soniya va soniyaning kasr qismi |
+0500 |
UTCdan siljish (offset) |
+05 |
vaqt zonasi nomi; tizimga qarab boshqa nom bo‘lishi mumkin |
m=+... |
time.Time ichidagi ixtiyoriy monotonic clock o‘qishi |
Monotonic vaqt nima?
Devor vaqti (wall clock) foydalanuvchi ko‘radigan sana va soatdir. U tizim vaqti tuzatilganda, NTP sinxronizatsiyasida yoki administrator o‘zgartirganda oldinga yoxud orqaga siljishi mumkin.
Monotonic clock esa o‘tgan davomiylikni o‘lchashga mo‘ljallangan va devor vaqtidagi tuzatishlardan ta’sirlanmaydi. time.Now() qaytargan qiymat monotonic o‘qishni ham saqlashi mumkin. Sub, Before, After va taqqoslash amallari ikkala operandda ham monotonic ma’lumot bo‘lsa, davomiylikni shu o‘qish asosida hisoblaydi.
m=+... qiymatini “dastur ishga tushganidan beri o‘tgan vaqt” deb talqin qilish kerak emas. U runtime chiqaradigan ichki monotonic ko‘rsatkich bo‘lib, saqlash yoki tizimlar orasida uzatish uchun mo‘ljallanmagan. Formatlash va serializatsiya odatda monotonic qismini olib tashlaydi.
Sana va vaqt qismlarini olish
time.Time metodlari alohida qismlarni qaytaradi:
package main
import (
"fmt"
"time"
)
func main() {
moment := time.Date(2024, time.February, 29, 16, 45, 30, 0, time.UTC)
fmt.Println("Yil:", moment.Year())
fmt.Println("Oy:", moment.Month())
fmt.Println("Kun:", moment.Day())
fmt.Println("Hafta kuni:", moment.Weekday())
fmt.Println("Soat:", moment.Hour())
fmt.Println("Daqiqa:", moment.Minute())
fmt.Println("Soniya:", moment.Second())
}
Natija:
Misolda qattiq berilgan vaqt ishlatilgani uchun natija barqaror. Month() time.Month turini qaytaradi va matnda inglizcha oy nomi sifatida ko‘rinadi. Mahalliylashtirilgan o‘zbekcha oy nomlari kerak bo‘lsa, ularni ilova darajasida alohida moslashtirish lozim.
Vaqtni formatlash
Format vaqtni satrga aylantiradi. Go boshqa ko‘p tillardagi YYYY-MM-DD belgilaridan foydalanmaydi. Layout — Go’ning maxsus namuna sanasi orqali yoziladi:
Esda saqlash uchun raqamlar ketma-ketligi: 01/02 03:04:05PM '06 -0700. Layoutdagi qismlar aynan shu namuna vaqtidagi qiymatlar bilan ifodalanadi.
package main
import (
"fmt"
"time"
)
func main() {
moment := time.Date(2024, time.August, 9, 16, 7, 5, 123_000_000, time.UTC)
fmt.Println("Sana:", moment.Format("02-01-2006"))
fmt.Println("Vaqt:", moment.Format("15:04:05"))
fmt.Println("API:", moment.Format(time.RFC3339Nano))
}
Natija:
02-01-2006 kun-oy-yil, 15:04:05 esa 24 soatlik vaqt ko‘rinishini beradi. API va tizimlar orasidagi almashinuv uchun time.RFC3339 yoki aniqlikni saqlash kerak bo‘lsa time.RFC3339Nano kabi tayyor layoutlardan foydalanish ma’qul.
Asosiy layout qismlari
| Layout qismi | Natija ma’nosi |
|---|---|
2006 |
to‘rt xonali yil |
06 |
ikki xonali yil |
01 |
ikki xonali oy |
1 |
bosh nol qo‘yilmagan oy |
Jan |
qisqa oy nomi |
January |
to‘liq oy nomi |
02 |
ikki xonali kun |
2 |
bosh nol qo‘yilmagan kun |
Mon |
qisqa hafta kuni |
Monday |
to‘liq hafta kuni |
15 |
24 soatlik soat |
03 |
12 soatlik soat |
PM yoki pm |
12 soatlik davr belgisi |
04 |
daqiqa |
05 |
soniya |
.000 |
millisekund, doim uch xona |
.000000 |
mikrosekund, doim olti xona |
.000000000 |
nanosekund, doim to‘qqiz xona |
MST |
zona nomi |
-0700 |
+0500 ko‘rinishidagi offset |
-07:00 |
+05:00 ko‘rinishidagi offset |
Z07:00 |
UTC uchun Z, boshqa zonada sonli offset |
Layoutda 2006 o‘rniga odatiy YYYY yozilsa, Go uni yil belgisi deb tanimaydi va oddiy matn sifatida chiqaradi:
Bu kod kompilyatsiyadan o‘tadi, ammo kutilgan sana o‘rniga layoutdagi oddiy harflarni chiqaradi. Shu sabab format xatosi runtime’da darhol xato qaytarmasligi mumkin.
Satrni vaqtga aylantirish
time.Parse satrni layout bo‘yicha tahlil qilib, time.Time qaytaradi:
package main
import (
"fmt"
"time"
)
func main() {
input := "2024-08-09"
moment, err := time.Parse("2006-01-02", input)
if err != nil {
fmt.Println("Sana noto‘g‘ri:", err)
return
}
fmt.Println(moment.Format(time.RFC3339))
}
Natija:
Layoutda zona bo‘lmasa, time.Parse vaqtni UTCda yaratadi. Vaqt ko‘rsatilmagan qismlar nol qiymat oladi, shu sabab soat 00:00:00.
Satr layoutga to‘liq mos kelishi kerak. Masalan, 2024-02-30 mavjud bo‘lmagan sana bo‘lgani uchun xato qaytaradi. Tashqaridan kelgan sanada errni tekshirmaslik nol qiymat yoki noto‘g‘ri biznes qaroriga olib kelishi mumkin.
Ma’lum zonadagi mahalliy vaqtni parse qilish
Foydalanuvchi 2024-08-09 14:30 deb yuborsa, satrning o‘zida zona yo‘q. Ilova bu vaqt qaysi Locationga tegishli ekanini bilishi kerak:
package main
import (
"fmt"
"time"
)
func main() {
location, err := time.LoadLocation("Asia/Tashkent")
if err != nil {
fmt.Println("Vaqt zonasi yuklanmadi:", err)
return
}
input := "2024-08-09 14:30"
moment, err := time.ParseInLocation("2006-01-02 15:04", input, location)
if err != nil {
fmt.Println("Vaqt noto‘g‘ri:", err)
return
}
fmt.Println("Toshkent:", moment.Format(time.RFC3339))
fmt.Println("UTC:", moment.UTC().Format(time.RFC3339))
}
Natija:
ParseInLocation zonasi ko‘rsatilmagan qismlarni berilgan Location qoidalari bilan izohlaydi. UTC() vaqt nuqtasini o‘zgartirmaydi; faqat uni UTC ko‘rinishida qaytaradi.
time.LoadLocation operatsion tizimdagi IANA vaqt zonasi ma’lumotlariga tayanishi mumkin. Minimal container image’da zoneinfo bazasi bo‘lmasa, yuklash xato qaytaradi. Bunday muhitda zoneinfo paketini image’ga o‘rnatish yoki zarur bo‘lsa dasturga _ "time/tzdata" importi orqali ma’lumotni qo‘shish mumkin. Bu executable hajmini oshiradi, shuning uchun deployment talabi asosida tanlanadi.
Warning
time.FixedZone("UZT", 5*60*60) doimiy +05:00 zona yaratadi, ammo tarixiy yoki yozgi vaqt qoidalarini bilmaydi. Qoidalari o‘zgaradigan hududlar uchun time.LoadLocation bilan IANA nomidan foydalaning.
time.Date bilan vaqt yaratish
time.Date yil, oy, kun, vaqt va locationdan time.Time yaratadi:
package main
import (
"fmt"
"time"
)
func main() {
moment := time.Date(
2024,
time.August,
9,
14,
30,
0,
0,
time.UTC,
)
fmt.Println(moment.Format(time.RFC3339))
}
Natija:
Oy uchun 8 yozish kompilyatsiyadan o‘tadi, chunki time.Month butun son asosidagi tur. time.August yozuvi esa ma’noni aniqroq ko‘rsatadi.
time.Date diapazondan tashqaridagi qismlarni normalizatsiya qiladi. Masalan, yanvarning 32-kuni fevraldagi sanaga o‘tadi. Shuning uchun undan foydalanuvchi kiritgan sana to‘g‘riligini tekshiruvchi validator sifatida foydalanmang. Tashqi matn uchun qat’iy layout bilan time.Parse ishlating va xatoni tekshiring.
Duration: vaqt oralig‘i
time.Duration nanosekundlar sonini saqlaydigan int64 asosidagi tur. Tayyor konstantalar kodni tushunarli qiladi:
package main
import (
"fmt"
"time"
)
func main() {
start := time.Date(2024, time.January, 1, 12, 0, 0, 0, time.UTC)
duration := 90 * time.Minute
end := start.Add(duration)
fmt.Println("Boshlanish:", start.Format(time.RFC3339))
fmt.Println("Tugash:", end.Format(time.RFC3339))
fmt.Println("Davomiylik:", end.Sub(start))
}
Natija:
Asosiy birliklar: time.Nanosecond, time.Microsecond, time.Millisecond, time.Second, time.Minute va time.Hour. Kun uchun time.Day konstantasi yo‘q, chunki calendar kuni vaqt zonasi va yozgi vaqt almashinuvi sabab har doim 24 soat bo‘lavermaydi.
Konfiguratsiyadan kelgan "1h30m" kabi qiymatni time.ParseDuration bilan tekshirish mumkin:
Bu parcha 1.5sni 1500ms davomiylikka aylantiradi. Noma’lum birlik yoki noto‘g‘ri matn xato qaytaradi. Duration cheklangan int64 diapazoniga ega; juda katta qiymatlarni hisoblashda overflow ehtimolini hisobga olish kerak.
Add va AddDate farqi
Add aniq davomiylik qo‘shadi:
AddDate calendar bo‘yicha yil, oy va kun qo‘shadi:
nextMonth := moment.AddDate(0, 1, 0)
twoMonthsAgo := moment.AddDate(0, -2, 0)
nextWeek := moment.AddDate(0, 0, 7)
Add(24*time.Hour) va AddDate(0, 0, 1) bir xil tushuncha emas. Yozgi vaqt qo‘llanadigan zonada keyingi calendar kuni 23 yoki 25 real soatdan keyin kelishi mumkin. “Ertaga shu mahalliy soatda” uchun AddDate, “aniq 24 soatdan keyin” uchun Add(24*time.Hour) ishlatiladi.
Oy qo‘shishda ham normalizatsiyani hisobga oling. Masalan, ayrim oylarning 31-kuni yo‘q. AddDate natijani time.Date qoidalari bo‘yicha normalizatsiya qiladi. “Keyingi oyning oxirgi kuni” kabi biznes talabi uchun alohida calendar qoidasi yozish kerak.
Vaqt zonalari bilan ishlash
time.Timedagi location vaqt nuqtasini qanday ko‘rsatishni belgilaydi. In boshqa locationdagi ko‘rinishni qaytaradi:
package main
import (
"fmt"
"time"
)
func main() {
tashkent, err := time.LoadLocation("Asia/Tashkent")
if err != nil {
fmt.Println("Zona yuklanmadi:", err)
return
}
moment := time.Date(2024, time.January, 15, 9, 0, 0, 0, time.UTC)
fmt.Println("UTC:", moment.Format(time.RFC3339))
fmt.Println("Toshkent:", moment.In(tashkent).Format(time.RFC3339))
}
Natija:
In soat ko‘rinishini o‘zgartiradi, lekin vaqt chizig‘idagi nuqta o‘sha-o‘sha qoladi. Backend tizimlarda vaqtni UTCda saqlash va uzatish, foydalanuvchiga chiqarishda uning locationiga o‘tkazish odatda xatolarni kamaytiradi.
Faqat +05:00 offset hududning barcha tarixiy va kelajak qoidalarini ifodalamaydi. Asia/Tashkent kabi location nomi esa zoneinfo bazasidagi qoidalarni ishlatadi.
Vaqtlarni taqqoslash
Vaqt nuqtalarini Before, After va Equal bilan taqqoslang:
package main
import (
"fmt"
"time"
)
func main() {
utc := time.Date(2024, time.January, 1, 9, 0, 0, 0, time.UTC)
fixed := time.FixedZone("UTC+5", 5*60*60)
local := time.Date(2024, time.January, 1, 14, 0, 0, 0, fixed)
fmt.Println("Bir vaqt nuqtasimi:", utc.Equal(local))
fmt.Println("UTC oldinmi:", utc.Before(local))
}
Natija:
Soatlar va zonalar boshqa ko‘rinsa ham, ikkala qiymat bir xil vaqt nuqtasini ifodalaydi.
time.Timeni == bilan solishtirish uning location va monotonic ma’lumoti kabi ichki ko‘rinishini ham hisobga oladi. Shu sabab vaqt nuqtasining tengligi uchun Equal ishlating. time.Time map kaliti bo‘lishi kerak bo‘lsa, qiymatlarni oldindan bir xil ko‘rinishga keltirish talabini aniq belgilang.
Unix timestamp
Unix timestamp vaqtni Unix epoch — 1970-01-01T00:00:00Zdan o‘tgan soniyalar yoki kichikroq birliklarda ifodalaydi:
package main
import (
"fmt"
"time"
)
func main() {
moment := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
seconds := moment.Unix()
restored := time.Unix(seconds, 0).UTC()
fmt.Println("Timestamp:", seconds)
fmt.Println("Qayta tiklandi:", restored.Format(time.RFC3339))
}
Natija:
API shartnomasida birlikni aniq yozing. Soniyadagi timestampni millisekund deb talqin qilish juda uzoq yoki noto‘g‘ri sana hosil qiladi. Go’da Unix, UnixMilli, UnixMicro va UnixNano metodlari birlikni ochiq ko‘rsatadi.
Sonli timestamp vaqt zonasini saqlamaydi. U vaqt nuqtasini ifodalaydi; ko‘rsatish zonasi keyin tanlanadi.
JSON va API formatlari
time.Time standart encoding/json bilan odatda RFC 3339 matni sifatida yoziladi. Tizimlar orasida almashishda zona offseti bor aniq format ishlating:
Faqat sana kerak bo‘lsa, API shartnomasida YYYY-MM-DD ma’nosidagi Go layoutni 2006-01-02 deb belgilang. Tug‘ilgan kun kabi qiymatni yarim tun UTCga aylantirish ba’zi zonalarda oldingi yoki keyingi calendar kun sifatida ko‘rinishi mumkin. “Vaqt nuqtasi” va “calendar sanasi”ni ma’lumot modelida aralashtirmang.
Database turi ham talabga mos bo‘lishi kerak. Vaqt nuqtasi, mahalliy uchrashuv va faqat sanadan iborat qiymat bir xil semantikaga ega emas. Database driver va ustun turi timezone bilan qanday ishlashini tekshiring.
Sleep, timer va ticker
time.Sleep joriy goroutineni kamida berilgan davomiylikka to‘xtatadi:
Nol yoki manfiy duration berilsa, Sleep darhol qaytadi. Operatsion tizim scheduler’i sabab goroutine aynan belgilangan nanosekundda davom etishi kafolatlanmaydi.
Bir martalik kelajak signal uchun time.NewTimer, davriy signal uchun time.NewTicker ishlatiladi:
package main
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(20 * time.Millisecond)
defer timer.Stop()
<-timer.C
fmt.Println("Timer tugadi")
}
Natija:
timer.C signal keladigan kanaldir. Stop kerak bo‘lmay qolgan faol timer yoki tickerni to‘xtatishda muhim. Ticker iste’molchi sekin bo‘lsa, barcha oraliq ticklarni cheksiz navbatga yig‘maydi; dastur har bir tick albatta qayta ishlanadi degan taxminga tayanmasligi kerak.
time.Sleepni goroutine tugashini kutish uchun ishlatmang. Buning uchun WaitGroup yoki channel kerak. Timeout va bekor qilish uchun backend kodida ko‘pincha context.WithTimeout mos keladi.
O‘tgan vaqtni o‘lchash
Operatsiya qancha davom etganini time.Now va time.Since bilan o‘lchash mumkin:
start monotonic ma’lumotga ega bo‘lsa, time.Since devor vaqti tuzatilishidan ta’sirlanmaydi. Performance tahlilida bitta o‘lchovdan yakuniy xulosa chiqarmang; takroriy o‘lchov uchun Go benchmarklaridan foydalaning.
Vaqtga bog‘liq kodni testlash
Funksiya ichida time.Now()ni bevosita chaqirish test natijasini joriy vaqtga bog‘laydi. Vaqtni parametr yoki funksiya sifatida uzatish testni takrorlanuvchi qiladi:
package main
import (
"fmt"
"time"
)
func expired(now, deadline time.Time) bool {
return !now.Before(deadline)
}
func main() {
now := time.Date(2024, time.January, 1, 12, 0, 0, 0, time.UTC)
deadline := now.Add(30 * time.Minute)
fmt.Println(expired(now, deadline))
fmt.Println(expired(deadline, deadline))
}
Natija:
Chegara qoidasi bu yerda ochiq: now deadlinega teng bo‘lsa ham muddat tugagan hisoblanadi. Real loyihada aynan shu kabi > yoki >= biznes qarorini test bilan mustahkamlash kerak.
Murakkab servisda quyidagi kabi clock funksiya berish mumkin:
Ishlab chiqarish kodida time.Now, testda esa oldindan belgilangan vaqt qaytaruvchi funksiya uzatiladi. Timerlarga tayangan testlarda haqiqiy Sleep ishlatish testni sekin va beqaror qiladi; imkon qadar signal yoki boshqariladigan clockdan foydalaning.
Keng tarqalgan xatolar
time.Now()doim UTC qaytaradi deb o‘ylash. U mahalliy locationdan foydalanadi; UTC kerak bo‘lsatime.Now().UTC()yozing.- Layoutda
YYYY-MM-DDishlatish. Go layouti namuna vaqt qismlaridan tuziladi:2006-01-02. time.Parsexatosini tekshirmaslik. Noto‘g‘ri yoki mavjud bo‘lmagan sana rad etilishi kerak.- Zonasiz satrni noto‘g‘ri zonada parse qilish. UTC uchun
Parse, ma’lum mahalliy zona uchunParseInLocationishlating. - Offset va locationni bir xil deb hisoblash.
+05:00hududning tarixiy va DST qoidalarini saqlamaydi. - Calendar kuni doim 24 soat deb hisoblash. Calendar amal uchun
AddDate, aniq davomiylik uchunAddishlatiladi. - Vaqt nuqtalarini formatlangan satr yoki
==bilan solishtirish.Before,AftervaEqualmetodlarini ishlating. - Unix timestamp birligini ko‘rsatmaslik. Soniya, millisekund va nanosekundni API shartnomasida aniq belgilang.
time.Sleepbilan goroutine yoki testni sinxronlashtirish. Aniq signal va sinxronizatsiya vositasidan foydalaning.time.Timeichidagi monotonic qiymat serializatsiyada saqlanadi deb o‘ylash. Tizimlar orasida faqat devor vaqti hamda zona/offset uzatiladi.
Interviewda nimalarga e’tibor beriladi?
- Go layouti
Mon Jan 2 15:04:05 MST 2006namuna vaqtiga asoslanadi. time.Timevaqt nuqtasini,time.Durationesa davomiylikni ifodalaydi.Parsezonasiz qiymatni UTC deb oladi;ParseInLocationberilgan locationdan foydalanadi.Addaniq duration,AddDatecalendar yil, oy va kun bilan ishlaydi.- Vaqt nuqtasi tengligini
Equalbilan tekshirish kerak. time.Now()monotonic o‘qishni saqlashi mumkin, ammo u formatlash va serializatsiyada uzatilmaydi.- Saqlash va servislararo almashuvda odatda UTC, foydalanuvchiga ko‘rsatishda uning locationi ishlatiladi.
Xulosa
Go’da sana va vaqt bilan ishlash faqat Format chaqirishdan iborat emas. Vaqt nuqtasi, davomiylik va locationni alohida tushunish kerak. Satrlarni qat’iy layout bilan parse qiling, xatolarni tekshiring va tizimlar orasida zona offseti aniq bo‘lgan formatdan foydalaning.
Calendar hisoblarida AddDate, aniq vaqt oralig‘ida Add va Sub ishlatiladi. Vaqtlarni Equal, Before va After bilan solishtiring. Testlarda joriy vaqtni tashqaridan uzatish kodni barqaror va tekshiriladigan qiladi.