ArduinoVN
Đăng nhập Tham gia
Thư viện Code /u/linucat /31/03/2026

Thư viện TimeLib: xử lý timezone và DST trên Arduino

Thảo luận

TimeLib (Time by Michael Margolis) là thư viện xử lý thời gian phổ biến nhất cho Arduino. Nó cho phép set, get, format thời gian — kết hợp với RTC hoặc NTP để có giờ thật. Bài này hướng dẫn API, timezone Việt Nam (UTC+7), và xử lý DST cho dự án quốc tế.

1. TimeLib hoạt động thế nào?

TimeLib lưu giờ dưới dạng Unix timestamp — số giây từ 1/1/1970. Mọi format (giờ, phút, ngày, tháng) tính từ đó. Hoạt động trên mọi Arduino — chỉ là math, không cần phần cứng.

Tuy nhiên trên ESP32, nên dùng time.h của ESP-IDF (có sẵn) — hỗ trợ timezone string đầy đủ và NTP tự sync. Bài này giới thiệu cả 2.

2. Cài TimeLib

Library Manager → "Time" by Michael Margolis. Không có dependency.

3. API cơ bản TimeLib

#include 

void setup() {
  Serial.begin(115200);
  // Set time manually (timestamp 1717000000 = 2024-05-29 12:53:20 UTC)
  setTime(1717000000);
}

void loop() {
  Serial.printf("%04d-%02d-%02d %02d:%02d:%02d\n",
    year(), month(), day(), hour(), minute(), second());
  delay(1000);
}

Các hàm chính:

  • setTime(epoch) — đặt giờ.
  • year() month() day() hour() minute() second() — đọc hiện tại.
  • now() — Unix timestamp.
  • weekday() — 1 (Sun) đến 7 (Sat).
  • dayShortStr(n), monthShortStr(n) — string.

4. Sync với NTP (ESP32)

Cách native trên ESP32:

#include 
#include 

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "PASS");
  while (WiFi.status() != WL_CONNECTED) delay(500);

  // Vietnam: UTC+7, no DST
  configTime(7 * 3600, 0, "pool.ntp.org", "asia.pool.ntp.org");
  delay(1000);
}

void loop() {
  struct tm t;
  if (getLocalTime(&t)) {
    char buf[32];
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &t);
    Serial.println(buf);
  }
  delay(1000);
}

5. Timezone với POSIX TZ string

Cách "chuẩn" để xử lý timezone + DST:

// Vietnam: ICT+7, no DST
setenv("TZ", "ICT-7", 1);
tzset();

// New York: EST/EDT with DST rules
setenv("TZ", "EST5EDT,M3.2.0,M11.1.0", 1);
tzset();

// London: GMT/BST
setenv("TZ", "GMT0BST,M3.5.0/1,M10.5.0", 1);
tzset();

// Japan: JST+9 no DST
setenv("TZ", "JST-9", 1);
tzset();

POSIX TZ format: <STD><offset>[<DST>[/offset]][,Mm.w.d[/time],Mm.w.d[/time]]. Phức tạp nhưng powerful — system tự xử lý DST switch tự động.

6. Format time

// strftime — chuẩn C
char buf[64];
time_t t = time(nullptr);
struct tm* tm_info = localtime(&t);

strftime(buf, 64, "%H:%M:%S", tm_info);          // 14:30:55
strftime(buf, 64, "%A %d/%m/%Y", tm_info);       // Wednesday 29/05/2024
strftime(buf, 64, "%Y-%m-%dT%H:%M:%S", tm_info); // ISO 8601

Serial.println(buf);

Một số format code:

  • %Y — năm 4 số.
  • %m — tháng 01-12.
  • %d — ngày 01-31.
  • %H / %I — giờ 24h / 12h.
  • %M — phút.
  • %S — giây.
  • %A / %a — thứ full / 3 chữ.
  • %B / %b — tháng full / 3 chữ.

7. Tính khoảng cách thời gian

// 2 timestamp
time_t now = time(nullptr);
time_t target;
struct tm t = {};
t.tm_year = 2026 - 1900;
t.tm_mon = 0;     // 0 = January
t.tm_mday = 1;
target = mktime(&t);

long diff_sec = target - now;
int days = diff_sec / 86400;
Serial.printf("Tet 2026: con %d ngay\n", days);

8. RTC backup khi mất WiFi (DS3231)

NTP cần WiFi. Khi mất WiFi, có thể lấy giờ từ RTC. Cài thêm thư viện RTClib:

#include 
RTC_DS3231 rtc;

void setup() {
  rtc.begin();
  if (rtc.lostPower()) {
    // RTC mất điện hoặc lần đầu
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // dùng giờ compile
  }
}

void loop() {
  DateTime now = rtc.now();
  Serial.printf("%04d-%02d-%02d %02d:%02d:%02d\n",
    now.year(), now.month(), now.day(),
    now.hour(), now.minute(), now.second());
  delay(1000);
}

Pattern: ESP32 boot → cố sync NTP. Thành công → set RTC. Mất WiFi → đọc RTC.

9. Cron-like scheduling

Bật relay mỗi ngày 7h sáng:

void loop() {
  struct tm t;
  if (!getLocalTime(&t)) return;

  static int lastTrigger = -1;
  // Sáng 7h, chỉ trigger 1 lần
  if (t.tm_hour == 7 && t.tm_min == 0 && t.tm_yday != lastTrigger) {
    lastTrigger = t.tm_yday;
    digitalWrite(RELAY, HIGH);
    Serial.println("Morning trigger!");
  }
}

Lưu tm_yday (day of year) làm anti-double-trigger.

10. Múi giờ một số nước

Quốc giaPOSIX TZ
Việt NamICT-7
Thái LanICT-7
Nhật BảnJST-9
Hàn QuốcKST-9
Trung Quốc (cả nước)CST-8
SingaporeSGT-8
UKGMT0BST,M3.5.0/1,M10.5.0
US EastEST5EDT,M3.2.0,M11.1.0
US PacificPST8PDT,M3.2.0,M11.1.0
Đức / PhápCET-1CEST,M3.5.0,M10.5.0/3

11. Lỗi thường gặp

  • getLocalTime() return false: chưa sync NTP, chờ vài giây sau khi configTime().
  • Giờ lệch 7 tiếng: quên config timezone hoặc dùng offset sai (25200 thay vì 7).
  • RTC trôi 5 phút/tháng: dùng DS3231 (TCXO) thay vì DS1307 cơ bản.
  • Năm 2038: time_t 32-bit overflow. ESP32 dùng 64-bit, an toàn.

Liên quan

Áp dụng dự án Đồng hồ NTP ESP32 + OLED hoặc Đồng hồ báo thức OLED + DS3231. Đọc bài ESP32 deep sleep để wake theo lịch.

Thảo luận (0)

Đăng nhập để tham gia thảo luận.
Chưa có bình luận nào. Hãy là người đầu tiên!