1 | #![stable(feature = "duration_core", since = "1.25.0")] |
---|---|

2 | |

3 | //! Temporal quantification. |

4 | //! |

5 | //! # Examples: |

6 | //! |

7 | //! There are multiple ways to create a new [`Duration`]: |

8 | //! |

9 | //! ``` |

10 | //! # use std::time::Duration; |

11 | //! let five_seconds = Duration::from_secs(5); |

12 | //! assert_eq!(five_seconds, Duration::from_millis(5_000)); |

13 | //! assert_eq!(five_seconds, Duration::from_micros(5_000_000)); |

14 | //! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000)); |

15 | //! |

16 | //! let ten_seconds = Duration::from_secs(10); |

17 | //! let seven_nanos = Duration::from_nanos(7); |

18 | //! let total = ten_seconds + seven_nanos; |

19 | //! assert_eq!(total, Duration::new(10, 7)); |

20 | //! ``` |

21 | |

22 | use crate::fmt; |

23 | use crate::iter::Sum; |

24 | use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; |

25 | |

26 | const NANOS_PER_SEC: u32 = 1_000_000_000; |

27 | const NANOS_PER_MILLI: u32 = 1_000_000; |

28 | const NANOS_PER_MICRO: u32 = 1_000; |

29 | const MILLIS_PER_SEC: u64 = 1_000; |

30 | const MICROS_PER_SEC: u64 = 1_000_000; |

31 | |

32 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |

33 | #[repr(transparent)] |

34 | #[rustc_layout_scalar_valid_range_start( 0)] |

35 | #[rustc_layout_scalar_valid_range_end( 999_999_999)] |

36 | struct Nanoseconds(u32); |

37 | |

38 | impl Default for Nanoseconds { |

39 | #[inline] |

40 | fn default() -> Self { |

41 | // SAFETY: 0 is within the valid range |

42 | unsafe { Nanoseconds(0) } |

43 | } |

44 | } |

45 | |

46 | /// A `Duration` type to represent a span of time, typically used for system |

47 | /// timeouts. |

48 | /// |

49 | /// Each `Duration` is composed of a whole number of seconds and a fractional part |

50 | /// represented in nanoseconds. If the underlying system does not support |

51 | /// nanosecond-level precision, APIs binding a system timeout will typically round up |

52 | /// the number of nanoseconds. |

53 | /// |

54 | /// [`Duration`]s implement many common traits, including [`Add`], [`Sub`], and other |

55 | /// [`ops`] traits. It implements [`Default`] by returning a zero-length `Duration`. |

56 | /// |

57 | /// [`ops`]: crate::ops |

58 | /// |

59 | /// # Examples |

60 | /// |

61 | /// ``` |

62 | /// use std::time::Duration; |

63 | /// |

64 | /// let five_seconds = Duration::new(5, 0); |

65 | /// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5); |

66 | /// |

67 | /// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5); |

68 | /// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5); |

69 | /// |

70 | /// let ten_millis = Duration::from_millis(10); |

71 | /// ``` |

72 | /// |

73 | /// # Formatting `Duration` values |

74 | /// |

75 | /// `Duration` intentionally does not have a `Display` impl, as there are a |

76 | /// variety of ways to format spans of time for human readability. `Duration` |

77 | /// provides a `Debug` impl that shows the full precision of the value. |

78 | /// |

79 | /// The `Debug` output uses the non-ASCII "µs" suffix for microseconds. If your |

80 | /// program output may appear in contexts that cannot rely on full Unicode |

81 | /// compatibility, you may wish to format `Duration` objects yourself or use a |

82 | /// crate to do so. |

83 | #[stable(feature = "duration", since = "1.3.0")] |

84 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] |

85 | #[cfg_attr(not(test), rustc_diagnostic_item = "Duration")] |

86 | pub struct Duration { |

87 | secs: u64, |

88 | nanos: Nanoseconds, // Always 0 <= nanos < NANOS_PER_SEC |

89 | } |

90 | |

91 | impl Duration { |

92 | /// The duration of one second. |

93 | /// |

94 | /// # Examples |

95 | /// |

96 | /// ``` |

97 | /// #![feature(duration_constants)] |

98 | /// use std::time::Duration; |

99 | /// |

100 | /// assert_eq!(Duration::SECOND, Duration::from_secs(1)); |

101 | /// ``` |

102 | #[unstable(feature = "duration_constants", issue = "57391")] |

103 | pub const SECOND: Duration = Duration::from_secs(1); |

104 | |

105 | /// The duration of one millisecond. |

106 | /// |

107 | /// # Examples |

108 | /// |

109 | /// ``` |

110 | /// #![feature(duration_constants)] |

111 | /// use std::time::Duration; |

112 | /// |

113 | /// assert_eq!(Duration::MILLISECOND, Duration::from_millis(1)); |

114 | /// ``` |

115 | #[unstable(feature = "duration_constants", issue = "57391")] |

116 | pub const MILLISECOND: Duration = Duration::from_millis(1); |

117 | |

118 | /// The duration of one microsecond. |

119 | /// |

120 | /// # Examples |

121 | /// |

122 | /// ``` |

123 | /// #![feature(duration_constants)] |

124 | /// use std::time::Duration; |

125 | /// |

126 | /// assert_eq!(Duration::MICROSECOND, Duration::from_micros(1)); |

127 | /// ``` |

128 | #[unstable(feature = "duration_constants", issue = "57391")] |

129 | pub const MICROSECOND: Duration = Duration::from_micros(1); |

130 | |

131 | /// The duration of one nanosecond. |

132 | /// |

133 | /// # Examples |

134 | /// |

135 | /// ``` |

136 | /// #![feature(duration_constants)] |

137 | /// use std::time::Duration; |

138 | /// |

139 | /// assert_eq!(Duration::NANOSECOND, Duration::from_nanos(1)); |

140 | /// ``` |

141 | #[unstable(feature = "duration_constants", issue = "57391")] |

142 | pub const NANOSECOND: Duration = Duration::from_nanos(1); |

143 | |

144 | /// A duration of zero time. |

145 | /// |

146 | /// # Examples |

147 | /// |

148 | /// ``` |

149 | /// use std::time::Duration; |

150 | /// |

151 | /// let duration = Duration::ZERO; |

152 | /// assert!(duration.is_zero()); |

153 | /// assert_eq!(duration.as_nanos(), 0); |

154 | /// ``` |

155 | #[stable(feature = "duration_zero", since = "1.53.0")] |

156 | pub const ZERO: Duration = Duration::from_nanos(0); |

157 | |

158 | /// The maximum duration. |

159 | /// |

160 | /// May vary by platform as necessary. Must be able to contain the difference between |

161 | /// two instances of [`Instant`] or two instances of [`SystemTime`]. |

162 | /// This constraint gives it a value of about 584,942,417,355 years in practice, |

163 | /// which is currently used on all platforms. |

164 | /// |

165 | /// # Examples |

166 | /// |

167 | /// ``` |

168 | /// use std::time::Duration; |

169 | /// |

170 | /// assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1)); |

171 | /// ``` |

172 | /// [`Instant`]: ../../std/time/struct.Instant.html |

173 | /// [`SystemTime`]: ../../std/time/struct.SystemTime.html |

174 | #[stable(feature = "duration_saturating_ops", since = "1.53.0")] |

175 | pub const MAX: Duration = Duration::new(u64::MAX, NANOS_PER_SEC - 1); |

176 | |

177 | /// Creates a new `Duration` from the specified number of whole seconds and |

178 | /// additional nanoseconds. |

179 | /// |

180 | /// If the number of nanoseconds is greater than 1 billion (the number of |

181 | /// nanoseconds in a second), then it will carry over into the seconds provided. |

182 | /// |

183 | /// # Panics |

184 | /// |

185 | /// This constructor will panic if the carry from the nanoseconds overflows |

186 | /// the seconds counter. |

187 | /// |

188 | /// # Examples |

189 | /// |

190 | /// ``` |

191 | /// use std::time::Duration; |

192 | /// |

193 | /// let five_seconds = Duration::new(5, 0); |

194 | /// ``` |

195 | #[stable(feature = "duration", since = "1.3.0")] |

196 | #[inline] |

197 | #[must_use] |

198 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

199 | pub const fn new(secs: u64, nanos: u32) -> Duration { |

200 | let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { |

201 | Some(secs) => secs, |

202 | None => panic!("overflow in Duration::new"), |

203 | }; |

204 | let nanos = nanos % NANOS_PER_SEC; |

205 | // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range |

206 | Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } |

207 | } |

208 | |

209 | /// Creates a new `Duration` from the specified number of whole seconds. |

210 | /// |

211 | /// # Examples |

212 | /// |

213 | /// ``` |

214 | /// use std::time::Duration; |

215 | /// |

216 | /// let duration = Duration::from_secs(5); |

217 | /// |

218 | /// assert_eq!(5, duration.as_secs()); |

219 | /// assert_eq!(0, duration.subsec_nanos()); |

220 | /// ``` |

221 | #[stable(feature = "duration", since = "1.3.0")] |

222 | #[must_use] |

223 | #[inline] |

224 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

225 | pub const fn from_secs(secs: u64) -> Duration { |

226 | Duration::new(secs, 0) |

227 | } |

228 | |

229 | /// Creates a new `Duration` from the specified number of milliseconds. |

230 | /// |

231 | /// # Examples |

232 | /// |

233 | /// ``` |

234 | /// use std::time::Duration; |

235 | /// |

236 | /// let duration = Duration::from_millis(2569); |

237 | /// |

238 | /// assert_eq!(2, duration.as_secs()); |

239 | /// assert_eq!(569_000_000, duration.subsec_nanos()); |

240 | /// ``` |

241 | #[stable(feature = "duration", since = "1.3.0")] |

242 | #[must_use] |

243 | #[inline] |

244 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

245 | pub const fn from_millis(millis: u64) -> Duration { |

246 | Duration::new(millis / MILLIS_PER_SEC, ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI) |

247 | } |

248 | |

249 | /// Creates a new `Duration` from the specified number of microseconds. |

250 | /// |

251 | /// # Examples |

252 | /// |

253 | /// ``` |

254 | /// use std::time::Duration; |

255 | /// |

256 | /// let duration = Duration::from_micros(1_000_002); |

257 | /// |

258 | /// assert_eq!(1, duration.as_secs()); |

259 | /// assert_eq!(2000, duration.subsec_nanos()); |

260 | /// ``` |

261 | #[stable(feature = "duration_from_micros", since = "1.27.0")] |

262 | #[must_use] |

263 | #[inline] |

264 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

265 | pub const fn from_micros(micros: u64) -> Duration { |

266 | Duration::new(micros / MICROS_PER_SEC, ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO) |

267 | } |

268 | |

269 | /// Creates a new `Duration` from the specified number of nanoseconds. |

270 | /// |

271 | /// # Examples |

272 | /// |

273 | /// ``` |

274 | /// use std::time::Duration; |

275 | /// |

276 | /// let duration = Duration::from_nanos(1_000_000_123); |

277 | /// |

278 | /// assert_eq!(1, duration.as_secs()); |

279 | /// assert_eq!(123, duration.subsec_nanos()); |

280 | /// ``` |

281 | #[stable(feature = "duration_extras", since = "1.27.0")] |

282 | #[must_use] |

283 | #[inline] |

284 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

285 | pub const fn from_nanos(nanos: u64) -> Duration { |

286 | Duration::new(nanos / (NANOS_PER_SEC as u64), (nanos % (NANOS_PER_SEC as u64)) as u32) |

287 | } |

288 | |

289 | /// Returns true if this `Duration` spans no time. |

290 | /// |

291 | /// # Examples |

292 | /// |

293 | /// ``` |

294 | /// use std::time::Duration; |

295 | /// |

296 | /// assert!(Duration::ZERO.is_zero()); |

297 | /// assert!(Duration::new(0, 0).is_zero()); |

298 | /// assert!(Duration::from_nanos(0).is_zero()); |

299 | /// assert!(Duration::from_secs(0).is_zero()); |

300 | /// |

301 | /// assert!(!Duration::new(1, 1).is_zero()); |

302 | /// assert!(!Duration::from_nanos(1).is_zero()); |

303 | /// assert!(!Duration::from_secs(1).is_zero()); |

304 | /// ``` |

305 | #[must_use] |

306 | #[stable(feature = "duration_zero", since = "1.53.0")] |

307 | #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] |

308 | #[inline] |

309 | pub const fn is_zero(&self) -> bool { |

310 | self.secs == 0 && self.nanos.0 == 0 |

311 | } |

312 | |

313 | /// Returns the number of _whole_ seconds contained by this `Duration`. |

314 | /// |

315 | /// The returned value does not include the fractional (nanosecond) part of the |

316 | /// duration, which can be obtained using [`subsec_nanos`]. |

317 | /// |

318 | /// # Examples |

319 | /// |

320 | /// ``` |

321 | /// use std::time::Duration; |

322 | /// |

323 | /// let duration = Duration::new(5, 730023852); |

324 | /// assert_eq!(duration.as_secs(), 5); |

325 | /// ``` |

326 | /// |

327 | /// To determine the total number of seconds represented by the `Duration` |

328 | /// including the fractional part, use [`as_secs_f64`] or [`as_secs_f32`] |

329 | /// |

330 | /// [`as_secs_f64`]: Duration::as_secs_f64 |

331 | /// [`as_secs_f32`]: Duration::as_secs_f32 |

332 | /// [`subsec_nanos`]: Duration::subsec_nanos |

333 | #[stable(feature = "duration", since = "1.3.0")] |

334 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

335 | #[must_use] |

336 | #[inline] |

337 | pub const fn as_secs(&self) -> u64 { |

338 | self.secs |

339 | } |

340 | |

341 | /// Returns the fractional part of this `Duration`, in whole milliseconds. |

342 | /// |

343 | /// This method does **not** return the length of the duration when |

344 | /// represented by milliseconds. The returned number always represents a |

345 | /// fractional portion of a second (i.e., it is less than one thousand). |

346 | /// |

347 | /// # Examples |

348 | /// |

349 | /// ``` |

350 | /// use std::time::Duration; |

351 | /// |

352 | /// let duration = Duration::from_millis(5432); |

353 | /// assert_eq!(duration.as_secs(), 5); |

354 | /// assert_eq!(duration.subsec_millis(), 432); |

355 | /// ``` |

356 | #[stable(feature = "duration_extras", since = "1.27.0")] |

357 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

358 | #[must_use] |

359 | #[inline] |

360 | pub const fn subsec_millis(&self) -> u32 { |

361 | self.nanos.0 / NANOS_PER_MILLI |

362 | } |

363 | |

364 | /// Returns the fractional part of this `Duration`, in whole microseconds. |

365 | /// |

366 | /// This method does **not** return the length of the duration when |

367 | /// represented by microseconds. The returned number always represents a |

368 | /// fractional portion of a second (i.e., it is less than one million). |

369 | /// |

370 | /// # Examples |

371 | /// |

372 | /// ``` |

373 | /// use std::time::Duration; |

374 | /// |

375 | /// let duration = Duration::from_micros(1_234_567); |

376 | /// assert_eq!(duration.as_secs(), 1); |

377 | /// assert_eq!(duration.subsec_micros(), 234_567); |

378 | /// ``` |

379 | #[stable(feature = "duration_extras", since = "1.27.0")] |

380 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

381 | #[must_use] |

382 | #[inline] |

383 | pub const fn subsec_micros(&self) -> u32 { |

384 | self.nanos.0 / NANOS_PER_MICRO |

385 | } |

386 | |

387 | /// Returns the fractional part of this `Duration`, in nanoseconds. |

388 | /// |

389 | /// This method does **not** return the length of the duration when |

390 | /// represented by nanoseconds. The returned number always represents a |

391 | /// fractional portion of a second (i.e., it is less than one billion). |

392 | /// |

393 | /// # Examples |

394 | /// |

395 | /// ``` |

396 | /// use std::time::Duration; |

397 | /// |

398 | /// let duration = Duration::from_millis(5010); |

399 | /// assert_eq!(duration.as_secs(), 5); |

400 | /// assert_eq!(duration.subsec_nanos(), 10_000_000); |

401 | /// ``` |

402 | #[stable(feature = "duration", since = "1.3.0")] |

403 | #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] |

404 | #[must_use] |

405 | #[inline] |

406 | pub const fn subsec_nanos(&self) -> u32 { |

407 | self.nanos.0 |

408 | } |

409 | |

410 | /// Returns the total number of whole milliseconds contained by this `Duration`. |

411 | /// |

412 | /// # Examples |

413 | /// |

414 | /// ``` |

415 | /// use std::time::Duration; |

416 | /// |

417 | /// let duration = Duration::new(5, 730023852); |

418 | /// assert_eq!(duration.as_millis(), 5730); |

419 | /// ``` |

420 | #[stable(feature = "duration_as_u128", since = "1.33.0")] |

421 | #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] |

422 | #[must_use] |

423 | #[inline] |

424 | pub const fn as_millis(&self) -> u128 { |

425 | self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128 |

426 | } |

427 | |

428 | /// Returns the total number of whole microseconds contained by this `Duration`. |

429 | /// |

430 | /// # Examples |

431 | /// |

432 | /// ``` |

433 | /// use std::time::Duration; |

434 | /// |

435 | /// let duration = Duration::new(5, 730023852); |

436 | /// assert_eq!(duration.as_micros(), 5730023); |

437 | /// ``` |

438 | #[stable(feature = "duration_as_u128", since = "1.33.0")] |

439 | #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] |

440 | #[must_use] |

441 | #[inline] |

442 | pub const fn as_micros(&self) -> u128 { |

443 | self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128 |

444 | } |

445 | |

446 | /// Returns the total number of nanoseconds contained by this `Duration`. |

447 | /// |

448 | /// # Examples |

449 | /// |

450 | /// ``` |

451 | /// use std::time::Duration; |

452 | /// |

453 | /// let duration = Duration::new(5, 730023852); |

454 | /// assert_eq!(duration.as_nanos(), 5730023852); |

455 | /// ``` |

456 | #[stable(feature = "duration_as_u128", since = "1.33.0")] |

457 | #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] |

458 | #[must_use] |

459 | #[inline] |

460 | pub const fn as_nanos(&self) -> u128 { |

461 | self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128 |

462 | } |

463 | |

464 | /// Computes the absolute difference between `self` and `other`. |

465 | /// |

466 | /// # Examples |

467 | /// |

468 | /// Basic usage: |

469 | /// |

470 | /// ``` |

471 | /// #![feature(duration_abs_diff)] |

472 | /// use std::time::Duration; |

473 | /// |

474 | /// assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0)); |

475 | /// assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000)); |

476 | /// ``` |

477 | #[unstable(feature = "duration_abs_diff", issue = "117618")] |

478 | #[must_use= "this returns the result of the operation, \ |

479 | without modifying the original"] |

480 | #[inline] |

481 | pub const fn abs_diff(self, other: Duration) -> Duration { |

482 | if let Some(res) = self.checked_sub(other) { res } else { other.checked_sub(self).unwrap() } |

483 | } |

484 | |

485 | /// Checked `Duration` addition. Computes `self + other`, returning [`None`] |

486 | /// if overflow occurred. |

487 | /// |

488 | /// # Examples |

489 | /// |

490 | /// Basic usage: |

491 | /// |

492 | /// ``` |

493 | /// use std::time::Duration; |

494 | /// |

495 | /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1))); |

496 | /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None); |

497 | /// ``` |

498 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |

499 | #[must_use= "this returns the result of the operation, \ |

500 | without modifying the original"] |

501 | #[inline] |

502 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

503 | pub const fn checked_add(self, rhs: Duration) -> Option<Duration> { |

504 | if let Some(mut secs) = self.secs.checked_add(rhs.secs) { |

505 | let mut nanos = self.nanos.0 + rhs.nanos.0; |

506 | if nanos >= NANOS_PER_SEC { |

507 | nanos -= NANOS_PER_SEC; |

508 | if let Some(new_secs) = secs.checked_add(1) { |

509 | secs = new_secs; |

510 | } else { |

511 | return None; |

512 | } |

513 | } |

514 | debug_assert!(nanos < NANOS_PER_SEC); |

515 | Some(Duration::new(secs, nanos)) |

516 | } else { |

517 | None |

518 | } |

519 | } |

520 | |

521 | /// Saturating `Duration` addition. Computes `self + other`, returning [`Duration::MAX`] |

522 | /// if overflow occurred. |

523 | /// |

524 | /// # Examples |

525 | /// |

526 | /// ``` |

527 | /// #![feature(duration_constants)] |

528 | /// use std::time::Duration; |

529 | /// |

530 | /// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1)); |

531 | /// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX); |

532 | /// ``` |

533 | #[stable(feature = "duration_saturating_ops", since = "1.53.0")] |

534 | #[must_use= "this returns the result of the operation, \ |

535 | without modifying the original"] |

536 | #[inline] |

537 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

538 | pub const fn saturating_add(self, rhs: Duration) -> Duration { |

539 | match self.checked_add(rhs) { |

540 | Some(res) => res, |

541 | None => Duration::MAX, |

542 | } |

543 | } |

544 | |

545 | /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] |

546 | /// if the result would be negative or if overflow occurred. |

547 | /// |

548 | /// # Examples |

549 | /// |

550 | /// Basic usage: |

551 | /// |

552 | /// ``` |

553 | /// use std::time::Duration; |

554 | /// |

555 | /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1))); |

556 | /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None); |

557 | /// ``` |

558 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |

559 | #[must_use= "this returns the result of the operation, \ |

560 | without modifying the original"] |

561 | #[inline] |

562 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

563 | pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> { |

564 | if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { |

565 | let nanos = if self.nanos.0 >= rhs.nanos.0 { |

566 | self.nanos.0 - rhs.nanos.0 |

567 | } else if let Some(sub_secs) = secs.checked_sub(1) { |

568 | secs = sub_secs; |

569 | self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0 |

570 | } else { |

571 | return None; |

572 | }; |

573 | debug_assert!(nanos < NANOS_PER_SEC); |

574 | Some(Duration::new(secs, nanos)) |

575 | } else { |

576 | None |

577 | } |

578 | } |

579 | |

580 | /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`] |

581 | /// if the result would be negative or if overflow occurred. |

582 | /// |

583 | /// # Examples |

584 | /// |

585 | /// ``` |

586 | /// use std::time::Duration; |

587 | /// |

588 | /// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1)); |

589 | /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO); |

590 | /// ``` |

591 | #[stable(feature = "duration_saturating_ops", since = "1.53.0")] |

592 | #[must_use= "this returns the result of the operation, \ |

593 | without modifying the original"] |

594 | #[inline] |

595 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

596 | pub const fn saturating_sub(self, rhs: Duration) -> Duration { |

597 | match self.checked_sub(rhs) { |

598 | Some(res) => res, |

599 | None => Duration::ZERO, |

600 | } |

601 | } |

602 | |

603 | /// Checked `Duration` multiplication. Computes `self * other`, returning |

604 | /// [`None`] if overflow occurred. |

605 | /// |

606 | /// # Examples |

607 | /// |

608 | /// Basic usage: |

609 | /// |

610 | /// ``` |

611 | /// use std::time::Duration; |

612 | /// |

613 | /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2))); |

614 | /// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None); |

615 | /// ``` |

616 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |

617 | #[must_use= "this returns the result of the operation, \ |

618 | without modifying the original"] |

619 | #[inline] |

620 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

621 | pub const fn checked_mul(self, rhs: u32) -> Option<Duration> { |

622 | // Multiply nanoseconds as u64, because it cannot overflow that way. |

623 | let total_nanos = self.nanos.0 as u64 * rhs as u64; |

624 | let extra_secs = total_nanos / (NANOS_PER_SEC as u64); |

625 | let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; |

626 | if let Some(s) = self.secs.checked_mul(rhs as u64) { |

627 | if let Some(secs) = s.checked_add(extra_secs) { |

628 | debug_assert!(nanos < NANOS_PER_SEC); |

629 | return Some(Duration::new(secs, nanos)); |

630 | } |

631 | } |

632 | None |

633 | } |

634 | |

635 | /// Saturating `Duration` multiplication. Computes `self * other`, returning |

636 | /// [`Duration::MAX`] if overflow occurred. |

637 | /// |

638 | /// # Examples |

639 | /// |

640 | /// ``` |

641 | /// #![feature(duration_constants)] |

642 | /// use std::time::Duration; |

643 | /// |

644 | /// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2)); |

645 | /// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX); |

646 | /// ``` |

647 | #[stable(feature = "duration_saturating_ops", since = "1.53.0")] |

648 | #[must_use= "this returns the result of the operation, \ |

649 | without modifying the original"] |

650 | #[inline] |

651 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

652 | pub const fn saturating_mul(self, rhs: u32) -> Duration { |

653 | match self.checked_mul(rhs) { |

654 | Some(res) => res, |

655 | None => Duration::MAX, |

656 | } |

657 | } |

658 | |

659 | /// Checked `Duration` division. Computes `self / other`, returning [`None`] |

660 | /// if `other == 0`. |

661 | /// |

662 | /// # Examples |

663 | /// |

664 | /// Basic usage: |

665 | /// |

666 | /// ``` |

667 | /// use std::time::Duration; |

668 | /// |

669 | /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); |

670 | /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); |

671 | /// assert_eq!(Duration::new(2, 0).checked_div(0), None); |

672 | /// ``` |

673 | #[stable(feature = "duration_checked_ops", since = "1.16.0")] |

674 | #[must_use= "this returns the result of the operation, \ |

675 | without modifying the original"] |

676 | #[inline] |

677 | #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] |

678 | pub const fn checked_div(self, rhs: u32) -> Option<Duration> { |

679 | if rhs != 0 { |

680 | let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64)); |

681 | let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs); |

682 | nanos += |

683 | ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32; |

684 | debug_assert!(nanos < NANOS_PER_SEC); |

685 | Some(Duration::new(secs, nanos)) |

686 | } else { |

687 | None |

688 | } |

689 | } |

690 | |

691 | /// Returns the number of seconds contained by this `Duration` as `f64`. |

692 | /// |

693 | /// The returned value does include the fractional (nanosecond) part of the duration. |

694 | /// |

695 | /// # Examples |

696 | /// ``` |

697 | /// use std::time::Duration; |

698 | /// |

699 | /// let dur = Duration::new(2, 700_000_000); |

700 | /// assert_eq!(dur.as_secs_f64(), 2.7); |

701 | /// ``` |

702 | #[stable(feature = "duration_float", since = "1.38.0")] |

703 | #[must_use] |

704 | #[inline] |

705 | #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] |

706 | pub const fn as_secs_f64(&self) -> f64 { |

707 | (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) |

708 | } |

709 | |

710 | /// Returns the number of seconds contained by this `Duration` as `f32`. |

711 | /// |

712 | /// The returned value does include the fractional (nanosecond) part of the duration. |

713 | /// |

714 | /// # Examples |

715 | /// ``` |

716 | /// use std::time::Duration; |

717 | /// |

718 | /// let dur = Duration::new(2, 700_000_000); |

719 | /// assert_eq!(dur.as_secs_f32(), 2.7); |

720 | /// ``` |

721 | #[stable(feature = "duration_float", since = "1.38.0")] |

722 | #[must_use] |

723 | #[inline] |

724 | #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] |

725 | pub const fn as_secs_f32(&self) -> f32 { |

726 | (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) |

727 | } |

728 | |

729 | /// Creates a new `Duration` from the specified number of seconds represented |

730 | /// as `f64`. |

731 | /// |

732 | /// # Panics |

733 | /// This constructor will panic if `secs` is negative, overflows `Duration` or not finite. |

734 | /// |

735 | /// # Examples |

736 | /// ``` |

737 | /// use std::time::Duration; |

738 | /// |

739 | /// let res = Duration::from_secs_f64(0.0); |

740 | /// assert_eq!(res, Duration::new(0, 0)); |

741 | /// let res = Duration::from_secs_f64(1e-20); |

742 | /// assert_eq!(res, Duration::new(0, 0)); |

743 | /// let res = Duration::from_secs_f64(4.2e-7); |

744 | /// assert_eq!(res, Duration::new(0, 420)); |

745 | /// let res = Duration::from_secs_f64(2.7); |

746 | /// assert_eq!(res, Duration::new(2, 700_000_000)); |

747 | /// let res = Duration::from_secs_f64(3e10); |

748 | /// assert_eq!(res, Duration::new(30_000_000_000, 0)); |

749 | /// // subnormal float |

750 | /// let res = Duration::from_secs_f64(f64::from_bits(1)); |

751 | /// assert_eq!(res, Duration::new(0, 0)); |

752 | /// // conversion uses rounding |

753 | /// let res = Duration::from_secs_f64(0.999e-9); |

754 | /// assert_eq!(res, Duration::new(0, 1)); |

755 | /// ``` |

756 | #[stable(feature = "duration_float", since = "1.38.0")] |

757 | #[must_use] |

758 | #[inline] |

759 | pub fn from_secs_f64(secs: f64) -> Duration { |

760 | match Duration::try_from_secs_f64(secs) { |

761 | Ok(v) => v, |

762 | Err(e) => panic!("{}", e.description()), |

763 | } |

764 | } |

765 | |

766 | /// Creates a new `Duration` from the specified number of seconds represented |

767 | /// as `f32`. |

768 | /// |

769 | /// # Panics |

770 | /// This constructor will panic if `secs` is negative, overflows `Duration` or not finite. |

771 | /// |

772 | /// # Examples |

773 | /// ``` |

774 | /// use std::time::Duration; |

775 | /// |

776 | /// let res = Duration::from_secs_f32(0.0); |

777 | /// assert_eq!(res, Duration::new(0, 0)); |

778 | /// let res = Duration::from_secs_f32(1e-20); |

779 | /// assert_eq!(res, Duration::new(0, 0)); |

780 | /// let res = Duration::from_secs_f32(4.2e-7); |

781 | /// assert_eq!(res, Duration::new(0, 420)); |

782 | /// let res = Duration::from_secs_f32(2.7); |

783 | /// assert_eq!(res, Duration::new(2, 700_000_048)); |

784 | /// let res = Duration::from_secs_f32(3e10); |

785 | /// assert_eq!(res, Duration::new(30_000_001_024, 0)); |

786 | /// // subnormal float |

787 | /// let res = Duration::from_secs_f32(f32::from_bits(1)); |

788 | /// assert_eq!(res, Duration::new(0, 0)); |

789 | /// // conversion uses rounding |

790 | /// let res = Duration::from_secs_f32(0.999e-9); |

791 | /// assert_eq!(res, Duration::new(0, 1)); |

792 | /// ``` |

793 | #[stable(feature = "duration_float", since = "1.38.0")] |

794 | #[must_use] |

795 | #[inline] |

796 | pub fn from_secs_f32(secs: f32) -> Duration { |

797 | match Duration::try_from_secs_f32(secs) { |

798 | Ok(v) => v, |

799 | Err(e) => panic!("{}", e.description()), |

800 | } |

801 | } |

802 | |

803 | /// Multiplies `Duration` by `f64`. |

804 | /// |

805 | /// # Panics |

806 | /// This method will panic if result is negative, overflows `Duration` or not finite. |

807 | /// |

808 | /// # Examples |

809 | /// ``` |

810 | /// use std::time::Duration; |

811 | /// |

812 | /// let dur = Duration::new(2, 700_000_000); |

813 | /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000)); |

814 | /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0)); |

815 | /// ``` |

816 | #[stable(feature = "duration_float", since = "1.38.0")] |

817 | #[must_use= "this returns the result of the operation, \ |

818 | without modifying the original"] |

819 | #[inline] |

820 | pub fn mul_f64(self, rhs: f64) -> Duration { |

821 | Duration::from_secs_f64(rhs * self.as_secs_f64()) |

822 | } |

823 | |

824 | /// Multiplies `Duration` by `f32`. |

825 | /// |

826 | /// # Panics |

827 | /// This method will panic if result is negative, overflows `Duration` or not finite. |

828 | /// |

829 | /// # Examples |

830 | /// ``` |

831 | /// use std::time::Duration; |

832 | /// |

833 | /// let dur = Duration::new(2, 700_000_000); |

834 | /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641)); |

835 | /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0)); |

836 | /// ``` |

837 | #[stable(feature = "duration_float", since = "1.38.0")] |

838 | #[must_use= "this returns the result of the operation, \ |

839 | without modifying the original"] |

840 | #[inline] |

841 | pub fn mul_f32(self, rhs: f32) -> Duration { |

842 | Duration::from_secs_f32(rhs * self.as_secs_f32()) |

843 | } |

844 | |

845 | /// Divide `Duration` by `f64`. |

846 | /// |

847 | /// # Panics |

848 | /// This method will panic if result is negative, overflows `Duration` or not finite. |

849 | /// |

850 | /// # Examples |

851 | /// ``` |

852 | /// use std::time::Duration; |

853 | /// |

854 | /// let dur = Duration::new(2, 700_000_000); |

855 | /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611)); |

856 | /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599)); |

857 | /// ``` |

858 | #[stable(feature = "duration_float", since = "1.38.0")] |

859 | #[must_use= "this returns the result of the operation, \ |

860 | without modifying the original"] |

861 | #[inline] |

862 | pub fn div_f64(self, rhs: f64) -> Duration { |

863 | Duration::from_secs_f64(self.as_secs_f64() / rhs) |

864 | } |

865 | |

866 | /// Divide `Duration` by `f32`. |

867 | /// |

868 | /// # Panics |

869 | /// This method will panic if result is negative, overflows `Duration` or not finite. |

870 | /// |

871 | /// # Examples |

872 | /// ``` |

873 | /// use std::time::Duration; |

874 | /// |

875 | /// let dur = Duration::new(2, 700_000_000); |

876 | /// // note that due to rounding errors result is slightly |

877 | /// // different from 0.859_872_611 |

878 | /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580)); |

879 | /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599)); |

880 | /// ``` |

881 | #[stable(feature = "duration_float", since = "1.38.0")] |

882 | #[must_use= "this returns the result of the operation, \ |

883 | without modifying the original"] |

884 | #[inline] |

885 | pub fn div_f32(self, rhs: f32) -> Duration { |

886 | Duration::from_secs_f32(self.as_secs_f32() / rhs) |

887 | } |

888 | |

889 | /// Divide `Duration` by `Duration` and return `f64`. |

890 | /// |

891 | /// # Examples |

892 | /// ``` |

893 | /// #![feature(div_duration)] |

894 | /// use std::time::Duration; |

895 | /// |

896 | /// let dur1 = Duration::new(2, 700_000_000); |

897 | /// let dur2 = Duration::new(5, 400_000_000); |

898 | /// assert_eq!(dur1.div_duration_f64(dur2), 0.5); |

899 | /// ``` |

900 | #[unstable(feature = "div_duration", issue = "63139")] |

901 | #[must_use= "this returns the result of the operation, \ |

902 | without modifying the original"] |

903 | #[inline] |

904 | #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] |

905 | pub const fn div_duration_f64(self, rhs: Duration) -> f64 { |

906 | self.as_secs_f64() / rhs.as_secs_f64() |

907 | } |

908 | |

909 | /// Divide `Duration` by `Duration` and return `f32`. |

910 | /// |

911 | /// # Examples |

912 | /// ``` |

913 | /// #![feature(div_duration)] |

914 | /// use std::time::Duration; |

915 | /// |

916 | /// let dur1 = Duration::new(2, 700_000_000); |

917 | /// let dur2 = Duration::new(5, 400_000_000); |

918 | /// assert_eq!(dur1.div_duration_f32(dur2), 0.5); |

919 | /// ``` |

920 | #[unstable(feature = "div_duration", issue = "63139")] |

921 | #[must_use= "this returns the result of the operation, \ |

922 | without modifying the original"] |

923 | #[inline] |

924 | #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] |

925 | pub const fn div_duration_f32(self, rhs: Duration) -> f32 { |

926 | self.as_secs_f32() / rhs.as_secs_f32() |

927 | } |

928 | } |

929 | |

930 | #[stable(feature = "duration", since = "1.3.0")] |

931 | impl Add for Duration { |

932 | type Output = Duration; |

933 | |

934 | #[inline] |

935 | fn add(self, rhs: Duration) -> Duration { |

936 | self.checked_add(rhs).expect(msg:"overflow when adding durations") |

937 | } |

938 | } |

939 | |

940 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |

941 | impl AddAssign for Duration { |

942 | #[inline] |

943 | fn add_assign(&mut self, rhs: Duration) { |

944 | *self = *self + rhs; |

945 | } |

946 | } |

947 | |

948 | #[stable(feature = "duration", since = "1.3.0")] |

949 | impl Sub for Duration { |

950 | type Output = Duration; |

951 | |

952 | #[inline] |

953 | fn sub(self, rhs: Duration) -> Duration { |

954 | self.checked_sub(rhs).expect(msg:"overflow when subtracting durations") |

955 | } |

956 | } |

957 | |

958 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |

959 | impl SubAssign for Duration { |

960 | #[inline] |

961 | fn sub_assign(&mut self, rhs: Duration) { |

962 | *self = *self - rhs; |

963 | } |

964 | } |

965 | |

966 | #[stable(feature = "duration", since = "1.3.0")] |

967 | impl Mul<u32> for Duration { |

968 | type Output = Duration; |

969 | |

970 | #[inline] |

971 | fn mul(self, rhs: u32) -> Duration { |

972 | self.checked_mul(rhs).expect(msg:"overflow when multiplying duration by scalar") |

973 | } |

974 | } |

975 | |

976 | #[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")] |

977 | impl Mul<Duration> for u32 { |

978 | type Output = Duration; |

979 | |

980 | #[inline] |

981 | fn mul(self, rhs: Duration) -> Duration { |

982 | rhs * self |

983 | } |

984 | } |

985 | |

986 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |

987 | impl MulAssign<u32> for Duration { |

988 | #[inline] |

989 | fn mul_assign(&mut self, rhs: u32) { |

990 | *self = *self * rhs; |

991 | } |

992 | } |

993 | |

994 | #[stable(feature = "duration", since = "1.3.0")] |

995 | impl Div<u32> for Duration { |

996 | type Output = Duration; |

997 | |

998 | #[inline] |

999 | fn div(self, rhs: u32) -> Duration { |

1000 | self.checked_div(rhs).expect(msg:"divide by zero error when dividing duration by scalar") |

1001 | } |

1002 | } |

1003 | |

1004 | #[stable(feature = "time_augmented_assignment", since = "1.9.0")] |

1005 | impl DivAssign<u32> for Duration { |

1006 | #[inline] |

1007 | fn div_assign(&mut self, rhs: u32) { |

1008 | *self = *self / rhs; |

1009 | } |

1010 | } |

1011 | |

1012 | macro_rules! sum_durations { |

1013 | ($iter:expr) => {{ |

1014 | let mut total_secs: u64 = 0; |

1015 | let mut total_nanos: u64 = 0; |

1016 | |

1017 | for entry in $iter { |

1018 | total_secs = |

1019 | total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); |

1020 | total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) { |

1021 | Some(n) => n, |

1022 | None => { |

1023 | total_secs = total_secs |

1024 | .checked_add(total_nanos / NANOS_PER_SEC as u64) |

1025 | .expect("overflow in iter::sum over durations"); |

1026 | (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64 |

1027 | } |

1028 | }; |

1029 | } |

1030 | total_secs = total_secs |

1031 | .checked_add(total_nanos / NANOS_PER_SEC as u64) |

1032 | .expect("overflow in iter::sum over durations"); |

1033 | total_nanos = total_nanos % NANOS_PER_SEC as u64; |

1034 | Duration::new(total_secs, total_nanos as u32) |

1035 | }}; |

1036 | } |

1037 | |

1038 | #[stable(feature = "duration_sum", since = "1.16.0")] |

1039 | impl Sum for Duration { |

1040 | fn sum<I: Iterator<Item = Duration>>(iter: I) -> Duration { |

1041 | sum_durations!(iter) |

1042 | } |

1043 | } |

1044 | |

1045 | #[stable(feature = "duration_sum", since = "1.16.0")] |

1046 | impl<'a> Sum<&'a Duration> for Duration { |

1047 | fn sum<I: Iterator<Item = &'a Duration>>(iter: I) -> Duration { |

1048 | sum_durations!(iter) |

1049 | } |

1050 | } |

1051 | |

1052 | #[stable(feature = "duration_debug_impl", since = "1.27.0")] |

1053 | impl fmt::Debug for Duration { |

1054 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |

1055 | /// Formats a floating point number in decimal notation. |

1056 | /// |

1057 | /// The number is given as the `integer_part` and a fractional part. |

1058 | /// The value of the fractional part is `fractional_part / divisor`. So |

1059 | /// `integer_part` = 3, `fractional_part` = 12 and `divisor` = 100 |

1060 | /// represents the number `3.012`. Trailing zeros are omitted. |

1061 | /// |

1062 | /// `divisor` must not be above 100_000_000. It also should be a power |

1063 | /// of 10, everything else doesn't make sense. `fractional_part` has |

1064 | /// to be less than `10 * divisor`! |

1065 | /// |

1066 | /// A prefix and postfix may be added. The whole thing is padded |

1067 | /// to the formatter's `width`, if specified. |

1068 | fn fmt_decimal( |

1069 | f: &mut fmt::Formatter<'_>, |

1070 | integer_part: u64, |

1071 | mut fractional_part: u32, |

1072 | mut divisor: u32, |

1073 | prefix: &str, |

1074 | postfix: &str, |

1075 | ) -> fmt::Result { |

1076 | // Encode the fractional part into a temporary buffer. The buffer |

1077 | // only need to hold 9 elements, because `fractional_part` has to |

1078 | // be smaller than 10^9. The buffer is prefilled with '0' digits |

1079 | // to simplify the code below. |

1080 | let mut buf = [b'0'; 9]; |

1081 | |

1082 | // The next digit is written at this position |

1083 | let mut pos = 0; |

1084 | |

1085 | // We keep writing digits into the buffer while there are non-zero |

1086 | // digits left and we haven't written enough digits yet. |

1087 | while fractional_part > 0 && pos < f.precision().unwrap_or(9) { |

1088 | // Write new digit into the buffer |

1089 | buf[pos] = b'0'+ (fractional_part / divisor) as u8; |

1090 | |

1091 | fractional_part %= divisor; |

1092 | divisor /= 10; |

1093 | pos += 1; |

1094 | } |

1095 | |

1096 | // If a precision < 9 was specified, there may be some non-zero |

1097 | // digits left that weren't written into the buffer. In that case we |

1098 | // need to perform rounding to match the semantics of printing |

1099 | // normal floating point numbers. However, we only need to do work |

1100 | // when rounding up. This happens if the first digit of the |

1101 | // remaining ones is >= 5. |

1102 | let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 { |

1103 | // Round up the number contained in the buffer. We go through |

1104 | // the buffer backwards and keep track of the carry. |

1105 | let mut rev_pos = pos; |

1106 | let mut carry = true; |

1107 | while carry && rev_pos > 0 { |

1108 | rev_pos -= 1; |

1109 | |

1110 | // If the digit in the buffer is not '9', we just need to |

1111 | // increment it and can stop then (since we don't have a |

1112 | // carry anymore). Otherwise, we set it to '0' (overflow) |

1113 | // and continue. |

1114 | if buf[rev_pos] < b'9'{ |

1115 | buf[rev_pos] += 1; |

1116 | carry = false; |

1117 | } else { |

1118 | buf[rev_pos] = b'0'; |

1119 | } |

1120 | } |

1121 | |

1122 | // If we still have the carry bit set, that means that we set |

1123 | // the whole buffer to '0's and need to increment the integer |

1124 | // part. |

1125 | if carry { |

1126 | // If `integer_part == u64::MAX` and precision < 9, any |

1127 | // carry of the overflow during rounding of the |

1128 | // `fractional_part` into the `integer_part` will cause the |

1129 | // `integer_part` itself to overflow. Avoid this by using an |

1130 | // `Option<u64>`, with `None` representing `u64::MAX + 1`. |

1131 | integer_part.checked_add(1) |

1132 | } else { |

1133 | Some(integer_part) |

1134 | } |

1135 | } else { |

1136 | Some(integer_part) |

1137 | }; |

1138 | |

1139 | // Determine the end of the buffer: if precision is set, we just |

1140 | // use as many digits from the buffer (capped to 9). If it isn't |

1141 | // set, we only use all digits up to the last non-zero one. |

1142 | let end = f.precision().map(|p| crate::cmp::min(p, 9)).unwrap_or(pos); |

1143 | |

1144 | // This closure emits the formatted duration without emitting any |

1145 | // padding (padding is calculated below). |

1146 | let emit_without_padding = |f: &mut fmt::Formatter<'_>| { |

1147 | if let Some(integer_part) = integer_part { |

1148 | write!(f, "{}{} ", prefix, integer_part)?; |

1149 | } else { |

1150 | // u64::MAX + 1 == 18446744073709551616 |

1151 | write!(f, "{} 18446744073709551616", prefix)?; |

1152 | } |

1153 | |

1154 | // Write the decimal point and the fractional part (if any). |

1155 | if end > 0 { |

1156 | // SAFETY: We are only writing ASCII digits into the buffer and |

1157 | // it was initialized with '0's, so it contains valid UTF8. |

1158 | let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) }; |

1159 | |

1160 | // If the user request a precision > 9, we pad '0's at the end. |

1161 | let w = f.precision().unwrap_or(pos); |

1162 | write!(f, ".{:0<width$} ", s, width = w)?; |

1163 | } |

1164 | |

1165 | write!(f, "{} ", postfix) |

1166 | }; |

1167 | |

1168 | match f.width() { |

1169 | None => { |

1170 | // No `width` specified. There's no need to calculate the |

1171 | // length of the output in this case, just emit it. |

1172 | emit_without_padding(f) |

1173 | } |

1174 | Some(requested_w) => { |

1175 | // A `width` was specified. Calculate the actual width of |

1176 | // the output in order to calculate the required padding. |

1177 | // It consists of 4 parts: |

1178 | // 1. The prefix: is either "+" or "", so we can just use len(). |

1179 | // 2. The postfix: can be "µs" so we have to count UTF8 characters. |

1180 | let mut actual_w = prefix.len() + postfix.chars().count(); |

1181 | // 3. The integer part: |

1182 | if let Some(integer_part) = integer_part { |

1183 | if let Some(log) = integer_part.checked_ilog10() { |

1184 | // integer_part is > 0, so has length log10(x)+1 |

1185 | actual_w += 1 + log as usize; |

1186 | } else { |

1187 | // integer_part is 0, so has length 1. |

1188 | actual_w += 1; |

1189 | } |

1190 | } else { |

1191 | // integer_part is u64::MAX + 1, so has length 20 |

1192 | actual_w += 20; |

1193 | } |

1194 | // 4. The fractional part (if any): |

1195 | if end > 0 { |

1196 | let frac_part_w = f.precision().unwrap_or(pos); |

1197 | actual_w += 1 + frac_part_w; |

1198 | } |

1199 | |

1200 | if requested_w <= actual_w { |

1201 | // Output is already longer than `width`, so don't pad. |

1202 | emit_without_padding(f) |

1203 | } else { |

1204 | // We need to add padding. Use the `Formatter::padding` helper function. |

1205 | let default_align = fmt::Alignment::Left; |

1206 | let post_padding = f.padding(requested_w - actual_w, default_align)?; |

1207 | emit_without_padding(f)?; |

1208 | post_padding.write(f) |

1209 | } |

1210 | } |

1211 | } |

1212 | } |

1213 | |

1214 | // Print leading '+' sign if requested |

1215 | let prefix = if f.sign_plus() { "+"} else { ""}; |

1216 | |

1217 | if self.secs > 0 { |

1218 | fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s") |

1219 | } else if self.nanos.0 >= NANOS_PER_MILLI { |

1220 | fmt_decimal( |

1221 | f, |

1222 | (self.nanos.0 / NANOS_PER_MILLI) as u64, |

1223 | self.nanos.0 % NANOS_PER_MILLI, |

1224 | NANOS_PER_MILLI / 10, |

1225 | prefix, |

1226 | "ms", |

1227 | ) |

1228 | } else if self.nanos.0 >= NANOS_PER_MICRO { |

1229 | fmt_decimal( |

1230 | f, |

1231 | (self.nanos.0 / NANOS_PER_MICRO) as u64, |

1232 | self.nanos.0 % NANOS_PER_MICRO, |

1233 | NANOS_PER_MICRO / 10, |

1234 | prefix, |

1235 | "µs", |

1236 | ) |

1237 | } else { |

1238 | fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns") |

1239 | } |

1240 | } |

1241 | } |

1242 | |

1243 | /// An error which can be returned when converting a floating-point value of seconds |

1244 | /// into a [`Duration`]. |

1245 | /// |

1246 | /// This error is used as the error type for [`Duration::try_from_secs_f32`] and |

1247 | /// [`Duration::try_from_secs_f64`]. |

1248 | /// |

1249 | /// # Example |

1250 | /// |

1251 | /// ``` |

1252 | /// use std::time::Duration; |

1253 | /// |

1254 | /// if let Err(e) = Duration::try_from_secs_f32(-1.0) { |

1255 | /// println!("Failed conversion to Duration: {e}"); |

1256 | /// } |

1257 | /// ``` |

1258 | #[derive(Debug, Clone, PartialEq, Eq)] |

1259 | #[stable(feature = "duration_checked_float", since = "1.66.0")] |

1260 | pub struct TryFromFloatSecsError { |

1261 | kind: TryFromFloatSecsErrorKind, |

1262 | } |

1263 | |

1264 | impl TryFromFloatSecsError { |

1265 | const fn description(&self) -> &'static str { |

1266 | match self.kind { |

1267 | TryFromFloatSecsErrorKind::Negative => { |

1268 | "can not convert float seconds to Duration: value is negative" |

1269 | } |

1270 | TryFromFloatSecsErrorKind::OverflowOrNan => { |

1271 | "can not convert float seconds to Duration: value is either too big or NaN" |

1272 | } |

1273 | } |

1274 | } |

1275 | } |

1276 | |

1277 | #[stable(feature = "duration_checked_float", since = "1.66.0")] |

1278 | impl fmt::Display for TryFromFloatSecsError { |

1279 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |

1280 | self.description().fmt(f) |

1281 | } |

1282 | } |

1283 | |

1284 | #[derive(Debug, Clone, PartialEq, Eq)] |

1285 | enum TryFromFloatSecsErrorKind { |

1286 | // Value is negative. |

1287 | Negative, |

1288 | // Value is either too big to be represented as `Duration` or `NaN`. |

1289 | OverflowOrNan, |

1290 | } |

1291 | |

1292 | macro_rules! try_from_secs { |

1293 | ( |

1294 | secs = $secs: expr, |

1295 | mantissa_bits = $mant_bits: literal, |

1296 | exponent_bits = $exp_bits: literal, |

1297 | offset = $offset: literal, |

1298 | bits_ty = $bits_ty:ty, |

1299 | double_ty = $double_ty:ty, |

1300 | ) => {{ |

1301 | const MIN_EXP: i16 = 1 - (1i16 << $exp_bits) / 2; |

1302 | const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1; |

1303 | const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1; |

1304 | |

1305 | if $secs < 0.0 { |

1306 | return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative }); |

1307 | } |

1308 | |

1309 | let bits = $secs.to_bits(); |

1310 | let mant = (bits & MANT_MASK) | (MANT_MASK + 1); |

1311 | let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP; |

1312 | |

1313 | let (secs, nanos) = if exp < -31 { |

1314 | // the input represents less than 1ns and can not be rounded to it |

1315 | (0u64, 0u32) |

1316 | } else if exp < 0 { |

1317 | // the input is less than 1 second |

1318 | let t = <$double_ty>::from(mant) << ($offset + exp); |

1319 | let nanos_offset = $mant_bits + $offset; |

1320 | let nanos_tmp = u128::from(NANOS_PER_SEC) * u128::from(t); |

1321 | let nanos = (nanos_tmp >> nanos_offset) as u32; |

1322 | |

1323 | let rem_mask = (1 << nanos_offset) - 1; |

1324 | let rem_msb_mask = 1 << (nanos_offset - 1); |

1325 | let rem = nanos_tmp & rem_mask; |

1326 | let is_tie = rem == rem_msb_mask; |

1327 | let is_even = (nanos & 1) == 0; |

1328 | let rem_msb = nanos_tmp & rem_msb_mask == 0; |

1329 | let add_ns = !(rem_msb || (is_even && is_tie)); |

1330 | |

1331 | // f32 does not have enough precision to trigger the second branch |

1332 | // since it can not represent numbers between 0.999_999_940_395 and 1.0. |

1333 | let nanos = nanos + add_ns as u32; |

1334 | if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) { (0, nanos) } else { (1, 0) } |

1335 | } else if exp < $mant_bits { |

1336 | let secs = u64::from(mant >> ($mant_bits - exp)); |

1337 | let t = <$double_ty>::from((mant << exp) & MANT_MASK); |

1338 | let nanos_offset = $mant_bits; |

1339 | let nanos_tmp = <$double_ty>::from(NANOS_PER_SEC) * t; |

1340 | let nanos = (nanos_tmp >> nanos_offset) as u32; |

1341 | |

1342 | let rem_mask = (1 << nanos_offset) - 1; |

1343 | let rem_msb_mask = 1 << (nanos_offset - 1); |

1344 | let rem = nanos_tmp & rem_mask; |

1345 | let is_tie = rem == rem_msb_mask; |

1346 | let is_even = (nanos & 1) == 0; |

1347 | let rem_msb = nanos_tmp & rem_msb_mask == 0; |

1348 | let add_ns = !(rem_msb || (is_even && is_tie)); |

1349 | |

1350 | // f32 does not have enough precision to trigger the second branch. |

1351 | // For example, it can not represent numbers between 1.999_999_880... |

1352 | // and 2.0. Bigger values result in even smaller precision of the |

1353 | // fractional part. |

1354 | let nanos = nanos + add_ns as u32; |

1355 | if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) { |

1356 | (secs, nanos) |

1357 | } else { |

1358 | (secs + 1, 0) |

1359 | } |

1360 | } else if exp < 64 { |

1361 | // the input has no fractional part |

1362 | let secs = u64::from(mant) << (exp - $mant_bits); |

1363 | (secs, 0) |

1364 | } else { |

1365 | return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::OverflowOrNan }); |

1366 | }; |

1367 | |

1368 | Ok(Duration::new(secs, nanos)) |

1369 | }}; |

1370 | } |

1371 | |

1372 | impl Duration { |

1373 | /// The checked version of [`from_secs_f32`]. |

1374 | /// |

1375 | /// [`from_secs_f32`]: Duration::from_secs_f32 |

1376 | /// |

1377 | /// This constructor will return an `Err` if `secs` is negative, overflows `Duration` or not finite. |

1378 | /// |

1379 | /// # Examples |

1380 | /// ``` |

1381 | /// use std::time::Duration; |

1382 | /// |

1383 | /// let res = Duration::try_from_secs_f32(0.0); |

1384 | /// assert_eq!(res, Ok(Duration::new(0, 0))); |

1385 | /// let res = Duration::try_from_secs_f32(1e-20); |

1386 | /// assert_eq!(res, Ok(Duration::new(0, 0))); |

1387 | /// let res = Duration::try_from_secs_f32(4.2e-7); |

1388 | /// assert_eq!(res, Ok(Duration::new(0, 420))); |

1389 | /// let res = Duration::try_from_secs_f32(2.7); |

1390 | /// assert_eq!(res, Ok(Duration::new(2, 700_000_048))); |

1391 | /// let res = Duration::try_from_secs_f32(3e10); |

1392 | /// assert_eq!(res, Ok(Duration::new(30_000_001_024, 0))); |

1393 | /// // subnormal float: |

1394 | /// let res = Duration::try_from_secs_f32(f32::from_bits(1)); |

1395 | /// assert_eq!(res, Ok(Duration::new(0, 0))); |

1396 | /// |

1397 | /// let res = Duration::try_from_secs_f32(-5.0); |

1398 | /// assert!(res.is_err()); |

1399 | /// let res = Duration::try_from_secs_f32(f32::NAN); |

1400 | /// assert!(res.is_err()); |

1401 | /// let res = Duration::try_from_secs_f32(2e19); |

1402 | /// assert!(res.is_err()); |

1403 | /// |

1404 | /// // the conversion uses rounding with tie resolution to even |

1405 | /// let res = Duration::try_from_secs_f32(0.999e-9); |

1406 | /// assert_eq!(res, Ok(Duration::new(0, 1))); |

1407 | /// |

1408 | /// // this float represents exactly 976562.5e-9 |

1409 | /// let val = f32::from_bits(0x3A80_0000); |

1410 | /// let res = Duration::try_from_secs_f32(val); |

1411 | /// assert_eq!(res, Ok(Duration::new(0, 976_562))); |

1412 | /// |

1413 | /// // this float represents exactly 2929687.5e-9 |

1414 | /// let val = f32::from_bits(0x3B40_0000); |

1415 | /// let res = Duration::try_from_secs_f32(val); |

1416 | /// assert_eq!(res, Ok(Duration::new(0, 2_929_688))); |

1417 | /// |

1418 | /// // this float represents exactly 1.000_976_562_5 |

1419 | /// let val = f32::from_bits(0x3F802000); |

1420 | /// let res = Duration::try_from_secs_f32(val); |

1421 | /// assert_eq!(res, Ok(Duration::new(1, 976_562))); |

1422 | /// |

1423 | /// // this float represents exactly 1.002_929_687_5 |

1424 | /// let val = f32::from_bits(0x3F806000); |

1425 | /// let res = Duration::try_from_secs_f32(val); |

1426 | /// assert_eq!(res, Ok(Duration::new(1, 2_929_688))); |

1427 | /// ``` |

1428 | #[stable(feature = "duration_checked_float", since = "1.66.0")] |

1429 | #[inline] |

1430 | pub fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError> { |

1431 | try_from_secs!( |

1432 | secs = secs, |

1433 | mantissa_bits = 23, |

1434 | exponent_bits = 8, |

1435 | offset = 41, |

1436 | bits_ty = u32, |

1437 | double_ty = u64, |

1438 | ) |

1439 | } |

1440 | |

1441 | /// The checked version of [`from_secs_f64`]. |

1442 | /// |

1443 | /// [`from_secs_f64`]: Duration::from_secs_f64 |

1444 | /// |

1445 | /// This constructor will return an `Err` if `secs` is negative, overflows `Duration` or not finite. |

1446 | /// |

1447 | /// # Examples |

1448 | /// ``` |

1449 | /// use std::time::Duration; |

1450 | /// |

1451 | /// let res = Duration::try_from_secs_f64(0.0); |

1452 | /// assert_eq!(res, Ok(Duration::new(0, 0))); |

1453 | /// let res = Duration::try_from_secs_f64(1e-20); |

1454 | /// assert_eq!(res, Ok(Duration::new(0, 0))); |

1455 | /// let res = Duration::try_from_secs_f64(4.2e-7); |

1456 | /// assert_eq!(res, Ok(Duration::new(0, 420))); |

1457 | /// let res = Duration::try_from_secs_f64(2.7); |

1458 | /// assert_eq!(res, Ok(Duration::new(2, 700_000_000))); |

1459 | /// let res = Duration::try_from_secs_f64(3e10); |

1460 | /// assert_eq!(res, Ok(Duration::new(30_000_000_000, 0))); |

1461 | /// // subnormal float |

1462 | /// let res = Duration::try_from_secs_f64(f64::from_bits(1)); |

1463 | /// assert_eq!(res, Ok(Duration::new(0, 0))); |

1464 | /// |

1465 | /// let res = Duration::try_from_secs_f64(-5.0); |

1466 | /// assert!(res.is_err()); |

1467 | /// let res = Duration::try_from_secs_f64(f64::NAN); |

1468 | /// assert!(res.is_err()); |

1469 | /// let res = Duration::try_from_secs_f64(2e19); |

1470 | /// assert!(res.is_err()); |

1471 | /// |

1472 | /// // the conversion uses rounding with tie resolution to even |

1473 | /// let res = Duration::try_from_secs_f64(0.999e-9); |

1474 | /// assert_eq!(res, Ok(Duration::new(0, 1))); |

1475 | /// let res = Duration::try_from_secs_f64(0.999_999_999_499); |

1476 | /// assert_eq!(res, Ok(Duration::new(0, 999_999_999))); |

1477 | /// let res = Duration::try_from_secs_f64(0.999_999_999_501); |

1478 | /// assert_eq!(res, Ok(Duration::new(1, 0))); |

1479 | /// let res = Duration::try_from_secs_f64(42.999_999_999_499); |

1480 | /// assert_eq!(res, Ok(Duration::new(42, 999_999_999))); |

1481 | /// let res = Duration::try_from_secs_f64(42.999_999_999_501); |

1482 | /// assert_eq!(res, Ok(Duration::new(43, 0))); |

1483 | /// |

1484 | /// // this float represents exactly 976562.5e-9 |

1485 | /// let val = f64::from_bits(0x3F50_0000_0000_0000); |

1486 | /// let res = Duration::try_from_secs_f64(val); |

1487 | /// assert_eq!(res, Ok(Duration::new(0, 976_562))); |

1488 | /// |

1489 | /// // this float represents exactly 2929687.5e-9 |

1490 | /// let val = f64::from_bits(0x3F68_0000_0000_0000); |

1491 | /// let res = Duration::try_from_secs_f64(val); |

1492 | /// assert_eq!(res, Ok(Duration::new(0, 2_929_688))); |

1493 | /// |

1494 | /// // this float represents exactly 1.000_976_562_5 |

1495 | /// let val = f64::from_bits(0x3FF0_0400_0000_0000); |

1496 | /// let res = Duration::try_from_secs_f64(val); |

1497 | /// assert_eq!(res, Ok(Duration::new(1, 976_562))); |

1498 | /// |

1499 | /// // this float represents exactly 1.002_929_687_5 |

1500 | /// let val = f64::from_bits(0x3_FF00_C000_0000_000); |

1501 | /// let res = Duration::try_from_secs_f64(val); |

1502 | /// assert_eq!(res, Ok(Duration::new(1, 2_929_688))); |

1503 | /// ``` |

1504 | #[stable(feature = "duration_checked_float", since = "1.66.0")] |

1505 | #[inline] |

1506 | pub fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError> { |

1507 | try_from_secs!( |

1508 | secs = secs, |

1509 | mantissa_bits = 52, |

1510 | exponent_bits = 11, |

1511 | offset = 44, |

1512 | bits_ty = u64, |

1513 | double_ty = u128, |

1514 | ) |

1515 | } |

1516 | } |

1517 |