@@ -109,7 +109,7 @@ void Alarm::cleanup() {
109109 using_independ_timezone_ = false ;
110110 timezone_offset_seconds_ = 0 ;
111111 state_ = State::kNone ;
112- next_utc_sec_ = 0 ;
112+ target_utc_sec_ = 0 ;
113113}
114114
115115void Alarm::refresh () {
@@ -123,7 +123,7 @@ void Alarm::refresh() {
123123uint32_t Alarm::remainSeconds () const {
124124 uint32_t curr_utc_sec = 0 ;
125125 if (state_ == State::kRunning && GetCurrentUtcTime (curr_utc_sec)) {
126- return next_utc_sec_ - curr_utc_sec;
126+ return target_utc_sec_ - curr_utc_sec;
127127 }
128128 return 0 ;
129129}
@@ -177,38 +177,46 @@ bool Alarm::activeTimer() {
177177 int timezone_offset_seconds = using_independ_timezone_ ? \
178178 timezone_offset_seconds_ : GetSystemTimezoneOffsetSeconds ();
179179
180- auto curr_local_sec = curr_utc_sec + timezone_offset_seconds;
181- uint32_t next_local_sec = next_utc_sec_ + timezone_offset_seconds;
180+ auto next_utc_start_sec = std::max (curr_utc_sec, target_utc_sec_);
182181
183- auto next_local_start_sec = std::max (curr_local_sec, next_local_sec);
184- // ! Q: 为什么要用curr_local_sec与next_utc_sec_中最大值来算下一轮的时间点?
182+ // ! Q: 为什么要用curr_utc_sec与target_utc_sec_中最大值来算下一轮的时间点?
185183 // ! A: 因为在实践中存在steady_clock比system_clock快的现象,会导致重复触发定时任务的问题。
186184 // ! 比如:定的时间为每天10:00:00.000触发,结果定时任务在09:59:59.995就触发了。如果下
187185 // ! 一轮的时间计算是从09:59:59:995计算,它会发现下一次的触发时间点在5ms之后。于是5ms
188186 // ! 之后就再次触发一次。
189187 // ! 解决办法就是:除了第一次按当前的时间算外,后面的如果出现提前触发的,按期望的算。
190188 // ! 就如上面的例子,就算是提前触发了,后面的按10:00:00.000计算。从而避免重复触发问题
189+
190+ uint32_t next_local_start_sec = next_utc_start_sec + timezone_offset_seconds;
191+ uint32_t next_local_sec = 0 ;
192+
191193 if (!calculateNextLocalTimeSec (next_local_start_sec, next_local_sec))
192194 return false ;
193195
194- auto remain_sec = next_local_sec - curr_local_sec;
196+ uint32_t next_utc_sec = next_local_sec - timezone_offset_seconds;
197+
198+ auto remain_sec = next_utc_sec - curr_utc_sec;
195199 // ! 提升精度,计算中需要等待的毫秒数
196200 auto remain_usec = (remain_sec * 1000 ) - (curr_utc_usec / 1000 );
197201
198202#if 1
199- LogTrace (" next_local_sec :%u, remain_sec:%u, remain_usec:%u" , next_local_sec , remain_sec, remain_usec);
203+ LogTrace (" next_utc_sec :%u, remain_sec:%u, remain_usec:%u" , next_utc_sec , remain_sec, remain_usec);
200204#endif
201205
202206 // ! 启动定时器
203207 sp_timer_ev_->initialize (std::chrono::milliseconds (remain_usec), event::Event::Mode::kOneshot );
204208 sp_timer_ev_->enable ();
205209
206210 state_ = State::kRunning ;
207- next_utc_sec_ = next_local_sec - timezone_offset_seconds ;
211+ target_utc_sec_ = next_utc_sec ;
208212 return true ;
209213}
210214
211215void Alarm::onTimeExpired () {
216+ #if 1
217+ LogTrace (" time expired, target_utc_sec:%u" , target_utc_sec_);
218+ #endif
219+
212220 state_ = State::kInited ;
213221 activeTimer ();
214222
0 commit comments