当前位置: 首页 > ai >正文

NTP库详解

NTPClient

NTPClient 库为 Arduino 提供了连接 NTP 服务器并获取准确时间的功能。

项目地址:https://github.com/arduino-libraries/NTPClient

UTC时间戳计算工具

https://www.epochconverter.com/

核心函数

构造函数

NTPClient(UDP& udp)

  • 功能:创建一个 NTPClient 对象,使用默认的 NTP 服务器 pool.ntp.org,无时间偏移,更新间隔为 60 秒。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

NTPClient(UDP& udp, long timeOffset)

  • 功能:创建一个 NTPClient 对象,指定时间偏移量(以秒为单位)。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
long offset = 3600; // 偏移1小时
//long offset = 8 * 3600; // 北京时间,东八区,偏移8小时
NTPClient timeClient(ntpUDP, offset);

NTPClient(UDP& udp, const char* poolServerName)

  • 功能:创建一个 NTPClient 对象,指定 NTP 服务器名称。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
const char* serverName = "europe.pool.ntp.org";
NTPClient timeClient(ntpUDP, serverName);

NTPClient(UDP& udp, IPAddress poolServerIP)

  • 功能:创建一个 NTPClient 对象,指定 NTP 服务器的 IP 地址。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
IPAddress serverIP(192, 168, 1, 100);
NTPClient timeClient(ntpUDP, serverIP);

NTPClient(UDP& udp, const char* poolServerName, long timeOffset)

  • 功能:创建一个 NTPClient 对象,指定 NTP 服务器名称和时间偏移量。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
const char* serverName = "europe.pool.ntp.org";
long offset = 3600;
NTPClient timeClient(ntpUDP, serverName, offset);

NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset)

  • 功能:创建一个 NTPClient 对象,指定 NTP 服务器的 IP 地址和时间偏移量。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
IPAddress serverIP(192, 168, 1, 100);
long offset = 3600;
NTPClient timeClient(ntpUDP, serverIP, offset);

NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval)

  • 功能:创建一个 NTPClient 对象,指定 NTP 服务器名称、时间偏移量和更新间隔(以毫秒为单位)。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
const char* serverName = "europe.pool.ntp.org";
long offset = 3600;
unsigned long interval = 120000; // 2分钟更新一次
NTPClient timeClient(ntpUDP, serverName, offset, interval);

NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval)

  • 功能:创建一个 NTPClient 对象,指定 NTP 服务器的 IP 地址、时间偏移量和更新间隔。
  • 示例
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
IPAddress serverIP(192, 168, 1, 100);
long offset = 3600;
unsigned long interval = 120000;
NTPClient timeClient(ntpUDP, serverIP, offset, interval);

成员函数

void begin()

  • 功能:启动底层 UDP 客户端,使用默认的本地端口 NTP_DEFAULT_LOCAL_PORT(1337)。
  • 示例
timeClient.begin();

void begin(unsigned int port)

  • 功能:启动底层 UDP 客户端,使用指定的本地端口。
  • 示例
unsigned int port = 1234;
timeClient.begin(port);

bool update()

  • 功能:根据更新间隔检查是否需要从 NTP 服务器更新时间。如果需要更新,则进行更新并返回 true;否则返回 false
  • 示例
if (timeClient.update()) {Serial.println("Time updated successfully");
} else {Serial.println("Time not updated");
}

bool forceUpdate()

  • 功能:强制从 NTP 服务器更新时间。更新成功返回 true,失败返回 false
  • 示例
if (timeClient.forceUpdate()) {Serial.println("Forced time update successful");
} else {Serial.println("Forced time update failed");
}

bool isTimeSet() const

  • 功能:检查 NTPClient 是否成功接收 NTP 数据包并设置了时间。如果时间已设置,返回 true;否则返回 false
  • 示例
if (timeClient.isTimeSet()) {Serial.println("Time is set");
} else {Serial.println("Time is not set");
}

int getDay() const

  • 功能:获取当前是星期几(0 表示星期日)。
  • 示例
int day = timeClient.getDay();
Serial.print("Day of the week: ");
Serial.println(day);

int getHours() const

  • 功能:获取当前小时数(0 - 23)。
  • 示例
int hours = timeClient.getHours();
Serial.print("Hours: ");
Serial.println(hours);

int getMinutes() const

  • 功能:获取当前分钟数(0 - 59)。
  • 示例
int minutes = timeClient.getMinutes();
Serial.print("Minutes: ");
Serial.println(minutes);

int getSeconds() const

  • 功能:获取当前秒数(0 - 59)。
  • 示例
int seconds = timeClient.getSeconds();
Serial.print("Seconds: ");
Serial.println(seconds);

String getFormattedTime() const

  • 功能:返回格式化的时间字符串,格式为 hh:mm:ss。有设置偏移的话,这个是偏移后的时间。
  • 示例
String formattedTime = timeClient.getFormattedTime();
Serial.println(formattedTime);

unsigned long getEpochTime() const

  • 功能:返回自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数(Unix 时间戳)。如果设置了时间偏移量,该偏移量将被添加到时间戳中。

时间戳(timestamp)是一个绝对的时间表示,通常定义为从1970 年 1 月 1 日 00:00:00
UTC
开始经过的秒数。时间戳与时区无关,无论你在哪个时区,同一时刻的时间戳都是相同的。

北京时间的时间戳与 UTC 时间戳在同一时刻应该是完全相同的,不需要加上时区偏移。

注意:NTP库函数定义:getEpochTime()返回值 = UTC纪元时间戳 + 时间偏移量

  • 示例
unsigned long epochTime = timeClient.getEpochTime();
Serial.print("Epoch time: ");
Serial.println(epochTime);
UTC纪元时间戳

1.在线工具

https://www.epochconverter.com/

2.python计算

from datetime import datetime, timedelta, timezonedef beijing_time_to_utc_timestamp(date_str, time_str="00:00:00"):"""将北京时间(格式:YYYY.M.D)转换为UTC纪元时间戳参数:- date_str: 日期字符串,例如 "2025.3.5"- time_str: 时间字符串,例如 "12:30:45"(默认00:00:00)返回:- utc_timestamp: UTC时间戳(秒级)- utc_time_str: UTC时间字符串(格式:YYYY-MM-DD HH:MM:SS)"""try:# 解析日期和时间year, month, day = map(int, date_str.split('.'))hour, minute, second = map(int, time_str.split(':'))# 创建北京时间的时区对象(UTC+8)beijing_tz = timezone(timedelta(hours=8))# 创建带时区的北京时间对象beijing_time = datetime(year, month, day, hour, minute, second, tzinfo=beijing_tz)# 转换为UTC时间utc_time = beijing_time.astimezone(timezone.utc)# 计算UTC时间戳utc_timestamp = int(utc_time.timestamp())# 格式化为字符串utc_time_str = utc_time.strftime("%Y-%m-%d %H:%M:%S")return utc_timestamp, utc_time_strexcept ValueError as ve:print(f"输入格式错误: {ve}")return None, Noneexcept Exception as e:print(f"发生未知错误: {e}")return None, None# 示例使用
if __name__ == "__main__":# 用户输入案例input_date = input("STEP 1/2:请输入日期(格式:年.月.日,例如:2025.3.5):")input_time = input("STEP 2/2:请输入时间(格式:时:分:秒,例如:12:30:45,默认为00:00:00):")# 处理默认时间if not input_time.strip():input_time = "00:00:00"# 计算UTC时间戳和UTC时间timestamp, utc_str = beijing_time_to_utc_timestamp(input_date, input_time)# 打印结果if timestamp is not None:print(f"输入北京时间:{input_date} {input_time}")print(f"对应的UTC时间:{utc_str}")print(f"UTC纪元时间戳(注意:NTP库getEpochTime() = UTC纪元时间戳 + 时间偏移量):{timestamp}")    

void end()

  • 功能:停止底层 UDP 客户端。
  • 示例
timeClient.end();

void setTimeOffset(int timeOffset)

  • 功能:设置时间偏移量(以秒为单位),可动态更改时区。
  • 示例
int offset = 7200; // 偏移2小时
timeClient.setTimeOffset(offset);

void setUpdateInterval(unsigned long updateInterval)

  • 功能:设置时间更新间隔(以毫秒为单位)。
  • 示例
unsigned long interval = 180000; // 3分钟更新一次
timeClient.setUpdateInterval(interval);

void setPoolServerName(const char* poolServerName)

  • 功能:设置 NTP 服务器名称。
  • 示例
const char* serverName = "asia.pool.ntp.org";
timeClient.setPoolServerName(serverName);

void setRandomPort(unsigned int minValue, unsigned int maxValue)

  • 功能:设置一个随机的本地端口,端口范围在 minValuemaxValue 之间。
  • 示例
unsigned int minPort = 49152;
unsigned int maxPort = 65535;
timeClient.setRandomPort(minPort, maxPort);

示例

格式化时间1

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>// WiFi网络信息
const char *ssid = "<SSID>";
const char *password = "<PASSWORD>";// NTP服务器地址
const char* ntpServerName = "ntp.aliyun.com";
// 北京时间所在时区为UTC+8
const long gmtOffset_sec = 8 * 3600;
// 设置NTP更新最小时间间隔,参数单位为毫秒
const int daylightOffset_sec = 60000;// 创建WiFiUDP对象
WiFiUDP ntpUDP;
// 创建NTPClient对象
NTPClient timeClient(ntpUDP, ntpServerName, gmtOffset_sec, daylightOffset_sec);void setup() {Serial.begin(115200);// 连接 WiFiWiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.println("Connecting to WiFi...");}Serial.println("Connected to WiFi");// 初始化 NTP 客户端timeClient.begin();
}void loop() {// 更新 NTP 时间timeClient.update();// 获取格式化后的时间字符串,HH:MM:SSString formattedTime = timeClient.getFormattedTime();// 打印原始格式化时间Serial.print("Formatted Time: ");Serial.println(formattedTime);// 提取小时、分钟和秒int hour, minute, second;  // 从格式化时间字符串中提取小时hour = formattedTime.substring(0, 2).toInt();  // 从格式化时间字符串中提取分钟minute = formattedTime.substring(3, 5).toInt();  // 从格式化时间字符串中提取秒second = formattedTime.substring(6, 8).toInt();// 打印提取的时间位Serial.print("Hour: ");Serial.print(hour);Serial.print(", Minute: ");Serial.print(minute);Serial.print(", Second: ");Serial.println(second);// timeClient.getEpochTime()返回自 1970-01-01 00:00:00 UTC 以来的秒数(即Unix时间戳)unsigned long epochTime = timeClient.getEpochTime();  Serial.print("Epoch Time: ");Serial.println(epochTime);delay(1000);
}

格式化时间2

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>// WiFi网络信息
const char *ssid = "<SSID>";
const char *password = "<PASSWORD>";// 创建WiFi UDP客户端
WiFiUDP ntpUDP;// 创建NTPClient对象,使用默认的NTP服务器,东八区(偏移28800秒),更新间隔为60秒
NTPClient timeClient(ntpUDP, "pool.ntp.org", 28800, 60000);// 定义中文星期数组
const char* weekDays[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};// 补零函数
String zeroPad(int num) {return (num < 10) ? "0" + String(num) : String(num);
}void setup() {// 初始化串口通信Serial.begin(115200);// 连接WiFiWiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected");// 启动NTPClienttimeClient.begin();
}void loop() {// 更新时间timeClient.update();// 获取星期、小时、分钟和秒int day = timeClient.getDay();int hours = timeClient.getHours();int minutes = timeClient.getMinutes();int seconds = timeClient.getSeconds();// 格式化输出String formattedTime = weekDays[day] + String(" ") + zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds);Serial.println(formattedTime);delay(1000); // 每秒更新一次
}

距离目标时间还有多久

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>// WiFi网络信息
const char *ssid = "<SSID>";
const char *password = "<PASSWORD>";// 创建WiFi UDP客户端
WiFiUDP ntpUDP;// 创建NTPClient对象,使用默认的NTP服务器,东八区(偏移28800秒),更新间隔为60秒
NTPClient timeClient(ntpUDP, "pool.ntp.org", 28800, 60000);// 2025年6月14日星期六凌晨12点00分 GMT+08:00
// 用https://www.epochconverter.com/在线工具计算时间戳
// 工具计算出的时间戳为UTC纪元时间戳,getEpochTime() = UTC纪元时间戳 + 时间偏移量
// 所以计算剩余时间,需要加上时区偏移
const unsigned long targetTime = 1749830400;void setup() {// 初始化串口通信Serial.begin(115200);// 连接WiFiWiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected");// 启动NTPClienttimeClient.begin();}void loop() {// 更新时间timeClient.update();Serial.println(timeClient.getFormattedTime());Serial.println(timeClient.getEpochTime());// 获取当前时间戳unsigned long currentTime = timeClient.getEpochTime();// 计算剩余时间,计算时间差需要加上时区偏移long remainingTime = targetTime - currentTime + 8 * 3600;if (remainingTime > 0) {// 显示剩余时间Serial.print("Remaining time: ");unsigned long days = remainingTime / (24 * 3600);String daysStr = days < 10 ? "0" + String(days) : String(days);Serial.print(daysStr);Serial.print("d:");remainingTime %= (24 * 3600);unsigned long hours = remainingTime / 3600;String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);Serial.print(hoursStr);Serial.print("h:");remainingTime %= 3600;unsigned long minutes = remainingTime / 60;String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);Serial.print(minuteStr);Serial.print("m:");unsigned long seconds = remainingTime % 60;String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);Serial.print(secondStr);Serial.println("s");} else {Serial.println("Countdown finished!");}delay(1000); // 每秒更新一次
}
http://www.xdnf.cn/news/10537.html

相关文章:

  • AI矢量软件|Illustrator 2025网盘下载与安装教程指南
  • Java从入门到精通 - 常用API(一)
  • 【Hot 100】70. 爬楼梯
  • 【农资进销存专用软件】佳易王农资进出库管理系统:赋能农业企业高效数字化管理
  • 94. Java 数字和字符串 - 按索引获取字符和子字符串
  • java28
  • 随记 nacos + openfegin 的远程调用找不到服务
  • 【CVE-2025-4123】Grafana完整分析SSRF和从xss到帐户接管
  • 深入探讨redis:缓存
  • AI入门——AI大模型、深度学习、机器学习总结
  • CentOS8.3+Kubernetes1.32.5+Docker28.2.2高可用集群二进制部署
  • 如何把电脑桌面设置在D盘?
  • JDK21深度解密 Day 11:云原生环境中的JDK21应用
  • 【Delphi】实现在多显示器时指定程序运行在某个显示器上
  • 力扣HOT100之动态规划:32. 最长有效括号
  • HTML 等价字符引用:系统化记忆指南
  • Fragment懒加载优化方案总结
  • DAY 43 复习日
  • Python 详细分析死锁原因及对应解决方案
  • 摩尔投票算法原理实现一文剖析
  • 基于 51 单片机的智能饮水机控制系统设计与实现
  • 低能硼注入的粒子控制 Axcelis Purion高电流离子注入机近晶圆环境中的石墨衬垫
  • BUUCTF[极客大挑战 2019]Secret File 1题解
  • 基于 Alpine 定制单功能用途(kiosk)电脑
  • 高效视频倍速播放插件推荐
  • 青少年编程与数学 02-020 C#程序设计基础 17课题、WEB与移动开发
  • C++中实现随机数(超详细!​​​​​)
  • 【Doris基础】Apache Doris中的Coordinator节点作用详解
  • 【MATLAB代码】制导——平行接近法,三维,目标是运动的,订阅专栏后可直接查看MATLAB源代码
  • C#项目07-二维数组的随机创建