| 192 | | return Duration( -m_ticks ); |
|---|
| | 214 | assert(Duration(5) + TickDuration.from!"usecs"(7) == Duration(75)); |
|---|
| | 215 | assert(Duration(5) - TickDuration.from!"usecs"(7) == Duration(-65)); |
|---|
| | 216 | assert(Duration(7) + TickDuration.from!"usecs"(5) == Duration(57)); |
|---|
| | 217 | assert(Duration(7) - TickDuration.from!"usecs"(5) == Duration(-43)); |
|---|
| | 218 | |
|---|
| | 219 | assert(Duration(5) + TickDuration.from!"usecs"(-7) == Duration(-65)); |
|---|
| | 220 | assert(Duration(5) - TickDuration.from!"usecs"(-7) == Duration(75)); |
|---|
| | 221 | assert(Duration(7) + TickDuration.from!"usecs"(-5) == Duration(-43)); |
|---|
| | 222 | assert(Duration(7) - TickDuration.from!"usecs"(-5) == Duration(57)); |
|---|
| | 223 | |
|---|
| | 224 | assert(Duration(-5) + TickDuration.from!"usecs"(7) == Duration(65)); |
|---|
| | 225 | assert(Duration(-5) - TickDuration.from!"usecs"(7) == Duration(-75)); |
|---|
| | 226 | assert(Duration(-7) + TickDuration.from!"usecs"(5) == Duration(43)); |
|---|
| | 227 | assert(Duration(-7) - TickDuration.from!"usecs"(5) == Duration(-57)); |
|---|
| | 228 | |
|---|
| | 229 | assert(Duration(-5) + TickDuration.from!"usecs"(-7) == Duration(-75)); |
|---|
| | 230 | assert(Duration(-5) - TickDuration.from!"usecs"(-7) == Duration(65)); |
|---|
| | 231 | assert(Duration(-7) + TickDuration.from!"usecs"(-5) == Duration(-57)); |
|---|
| | 232 | assert(Duration(-7) - TickDuration.from!"usecs"(-5) == Duration(43)); |
|---|
| | 233 | } |
|---|
| | 234 | |
|---|
| | 235 | auto hnsdur = Duration(12); |
|---|
| | 236 | const chnsdur = Duration(12); |
|---|
| | 237 | immutable ihnsdur = Duration(12); |
|---|
| | 238 | auto tdur = TickDuration.from!"usecs"(12); |
|---|
| | 239 | const ctdur = TickDuration.from!"usecs"(12); |
|---|
| | 240 | immutable itdur = TickDuration.from!"usecs"(12); |
|---|
| | 241 | static assert(__traits(compiles, hnsdur + hnsdur)); |
|---|
| | 242 | static assert(__traits(compiles, chnsdur + hnsdur)); |
|---|
| | 243 | static assert(__traits(compiles, ihnsdur + hnsdur)); |
|---|
| | 244 | static assert(__traits(compiles, hnsdur + chnsdur)); |
|---|
| | 245 | static assert(__traits(compiles, chnsdur + chnsdur)); |
|---|
| | 246 | static assert(__traits(compiles, ihnsdur + chnsdur)); |
|---|
| | 247 | static assert(__traits(compiles, hnsdur + ihnsdur)); |
|---|
| | 248 | static assert(__traits(compiles, chnsdur + ihnsdur)); |
|---|
| | 249 | static assert(__traits(compiles, ihnsdur + ihnsdur)); |
|---|
| | 250 | |
|---|
| | 251 | static assert(__traits(compiles, hnsdur + tdur)); |
|---|
| | 252 | static assert(__traits(compiles, chnsdur + tdur)); |
|---|
| | 253 | static assert(__traits(compiles, ihnsdur + tdur)); |
|---|
| | 254 | static assert(__traits(compiles, hnsdur + ctdur)); |
|---|
| | 255 | static assert(__traits(compiles, chnsdur + ctdur)); |
|---|
| | 256 | static assert(__traits(compiles, ihnsdur + ctdur)); |
|---|
| | 257 | static assert(__traits(compiles, hnsdur + itdur)); |
|---|
| | 258 | static assert(__traits(compiles, chnsdur + itdur)); |
|---|
| | 259 | static assert(__traits(compiles, ihnsdur + itdur)); |
|---|
| | 260 | |
|---|
| | 261 | static assert(__traits(compiles, hnsdur - hnsdur)); |
|---|
| | 262 | static assert(__traits(compiles, chnsdur - hnsdur)); |
|---|
| | 263 | static assert(__traits(compiles, ihnsdur - hnsdur)); |
|---|
| | 264 | static assert(__traits(compiles, hnsdur - chnsdur)); |
|---|
| | 265 | static assert(__traits(compiles, chnsdur - chnsdur)); |
|---|
| | 266 | static assert(__traits(compiles, ihnsdur - chnsdur)); |
|---|
| | 267 | static assert(__traits(compiles, hnsdur - ihnsdur)); |
|---|
| | 268 | static assert(__traits(compiles, chnsdur - ihnsdur)); |
|---|
| | 269 | static assert(__traits(compiles, ihnsdur - ihnsdur)); |
|---|
| | 270 | |
|---|
| | 271 | static assert(__traits(compiles, hnsdur - tdur)); |
|---|
| | 272 | static assert(__traits(compiles, chnsdur - tdur)); |
|---|
| | 273 | static assert(__traits(compiles, ihnsdur - tdur)); |
|---|
| | 274 | static assert(__traits(compiles, hnsdur - ctdur)); |
|---|
| | 275 | static assert(__traits(compiles, chnsdur - ctdur)); |
|---|
| | 276 | static assert(__traits(compiles, ihnsdur - ctdur)); |
|---|
| | 277 | static assert(__traits(compiles, hnsdur - itdur)); |
|---|
| | 278 | static assert(__traits(compiles, chnsdur - itdur)); |
|---|
| | 279 | static assert(__traits(compiles, ihnsdur - itdur)); |
|---|
| | 280 | } |
|---|
| | 281 | |
|---|
| | 282 | |
|---|
| | 283 | /++ |
|---|
| | 284 | Adds or subtracts two Durations as well as assigning the result |
|---|
| | 285 | to this Duration. |
|---|
| | 286 | |
|---|
| | 287 | The legal types of arithmetic for Duration using this operator are |
|---|
| | 288 | |
|---|
| | 289 | $(TABLE |
|---|
| | 290 | $(TR $(TD Duration) $(TD +) $(TD Duration) $(TD -->) $(TD Duration)) |
|---|
| | 291 | $(TR $(TD Duration) $(TD -) $(TD Duration) $(TD -->) $(TD Duration)) |
|---|
| | 292 | $(TR $(TD Duration) $(TD +) $(TD TickDuration) $(TD -->) $(TD Duration)) |
|---|
| | 293 | $(TR $(TD Duration) $(TD -) $(TD TickDuration) $(TD -->) $(TD Duration)) |
|---|
| | 294 | ) |
|---|
| | 295 | |
|---|
| | 296 | Params: |
|---|
| | 297 | rhs = The duration to add to or subtract from this DateTime. |
|---|
| | 298 | |
|---|
| | 299 | Note: |
|---|
| | 300 | TUnqual is just a local copy of std.traits' Unqual, since core does |
|---|
| | 301 | not have access to std.traits, and naming it Unqual as well would |
|---|
| | 302 | result in a name clash, so it's TUnqual. |
|---|
| | 303 | +/ |
|---|
| | 304 | /+ref+/ Duration opOpAssign(string op, D)(in D rhs) pure nothrow |
|---|
| | 305 | if((op == "+" || op == "-") && |
|---|
| | 306 | (is(TUnqual!D == Duration) || |
|---|
| | 307 | is(TUnqual!D == TickDuration))) |
|---|
| | 308 | { |
|---|
| | 309 | static if(is(TUnqual!D == Duration)) |
|---|
| | 310 | mixin("_hnsecs " ~ op ~ "= rhs._hnsecs;"); |
|---|
| | 311 | else if(is(TUnqual!D == TickDuration)) |
|---|
| | 312 | mixin("_hnsecs " ~ op ~ "= rhs.hnsecs;"); |
|---|
| | 313 | |
|---|
| | 314 | return this; |
|---|
| | 315 | } |
|---|
| | 316 | |
|---|
| | 317 | unittest |
|---|
| | 318 | { |
|---|
| | 319 | static void testDur(string op, D)(Duration dur, in D rhs, in Duration expected, size_t line = __LINE__) |
|---|
| | 320 | { |
|---|
| | 321 | if(mixin("dur " ~ op ~ " rhs") != expected) |
|---|
| | 322 | throw new AssertError("op failed", __FILE__, line); |
|---|
| | 323 | |
|---|
| | 324 | if(dur != expected) |
|---|
| | 325 | throw new AssertError("op assign failed", __FILE__, line); |
|---|
| | 326 | } |
|---|
| | 327 | |
|---|
| | 328 | testDur!"+="(Duration(5), Duration(7), Duration(12)); |
|---|
| | 329 | testDur!"-="(Duration(5), Duration(7), Duration(-2)); |
|---|
| | 330 | testDur!"+="(Duration(7), Duration(5), Duration(12)); |
|---|
| | 331 | testDur!"-="(Duration(7), Duration(5), Duration(2)); |
|---|
| | 332 | |
|---|
| | 333 | testDur!"+="(Duration(5), Duration(-7), Duration(-2)); |
|---|
| | 334 | testDur!"-="(Duration(5), Duration(-7), Duration(12)); |
|---|
| | 335 | testDur!"+="(Duration(7), Duration(-5), Duration(2)); |
|---|
| | 336 | testDur!"-="(Duration(7), Duration(-5), Duration(12)); |
|---|
| | 337 | |
|---|
| | 338 | testDur!"+="(Duration(-5), Duration(7), Duration(2)); |
|---|
| | 339 | testDur!"-="(Duration(-5), Duration(7), Duration(-12)); |
|---|
| | 340 | testDur!"+="(Duration(-7), Duration(5), Duration(-2)); |
|---|
| | 341 | testDur!"-="(Duration(-7), Duration(5), Duration(-12)); |
|---|
| | 342 | |
|---|
| | 343 | testDur!"+="(Duration(-5), Duration(-7), Duration(-12)); |
|---|
| | 344 | testDur!"-="(Duration(-5), Duration(-7), Duration(2)); |
|---|
| | 345 | testDur!"+="(Duration(-7), Duration(-5), Duration(-12)); |
|---|
| | 346 | testDur!"-="(Duration(-7), Duration(-5), Duration(-2)); |
|---|
| | 347 | |
|---|
| | 348 | //This should run the test on Linux systems (I don't know about other Posix systems), |
|---|
| | 349 | //but Windows doesn't seem to have a very round number for ticks per second |
|---|
| | 350 | //(1_193_182 in wine on my Linux box), so testing on Windows is harder. |
|---|
| | 351 | if(TickDuration.ticksPerSec == 1_000_000) |
|---|
| | 352 | { |
|---|
| | 353 | testDur!"+="(Duration(5), TickDuration.from!"usecs"(7), Duration(75)); |
|---|
| | 354 | testDur!"-="(Duration(5), TickDuration.from!"usecs"(7), Duration(-65)); |
|---|
| | 355 | testDur!"+="(Duration(7), TickDuration.from!"usecs"(5), Duration(57)); |
|---|
| | 356 | testDur!"-="(Duration(7), TickDuration.from!"usecs"(5), Duration(-43)); |
|---|
| | 357 | |
|---|
| | 358 | testDur!"+="(Duration(5), TickDuration.from!"usecs"(-7), Duration(-65)); |
|---|
| | 359 | testDur!"-="(Duration(5), TickDuration.from!"usecs"(-7), Duration(75)); |
|---|
| | 360 | testDur!"+="(Duration(7), TickDuration.from!"usecs"(-5), Duration(-43)); |
|---|
| | 361 | testDur!"-="(Duration(7), TickDuration.from!"usecs"(-5), Duration(57)); |
|---|
| | 362 | |
|---|
| | 363 | testDur!"+="(Duration(-5), TickDuration.from!"usecs"(7), Duration(65)); |
|---|
| | 364 | testDur!"-="(Duration(-5), TickDuration.from!"usecs"(7), Duration(-75)); |
|---|
| | 365 | testDur!"+="(Duration(-7), TickDuration.from!"usecs"(5), Duration(43)); |
|---|
| | 366 | testDur!"-="(Duration(-7), TickDuration.from!"usecs"(5), Duration(-57)); |
|---|
| | 367 | |
|---|
| | 368 | testDur!"+="(Duration(-5), TickDuration.from!"usecs"(-7), Duration(-75)); |
|---|
| | 369 | testDur!"-="(Duration(-5), TickDuration.from!"usecs"(-7), Duration(65)); |
|---|
| | 370 | testDur!"+="(Duration(-7), TickDuration.from!"usecs"(-5), Duration(-57)); |
|---|
| | 371 | testDur!"-="(Duration(-7), TickDuration.from!"usecs"(-5), Duration(43)); |
|---|
| | 372 | } |
|---|
| | 373 | |
|---|
| | 374 | auto hnsdur = Duration(12); |
|---|
| | 375 | const chnsdur = Duration(12); |
|---|
| | 376 | immutable ihnsdur = Duration(12); |
|---|
| | 377 | auto tdur = TickDuration.from!"usecs"(12); |
|---|
| | 378 | const ctdur = TickDuration.from!"usecs"(12); |
|---|
| | 379 | immutable itdur = TickDuration.from!"usecs"(12); |
|---|
| | 380 | static assert(__traits(compiles, hnsdur += hnsdur)); |
|---|
| | 381 | static assert(!__traits(compiles, chnsdur += hnsdur)); |
|---|
| | 382 | static assert(!__traits(compiles, ihnsdur += hnsdur)); |
|---|
| | 383 | static assert(__traits(compiles, hnsdur += chnsdur)); |
|---|
| | 384 | static assert(!__traits(compiles, chnsdur += chnsdur)); |
|---|
| | 385 | static assert(!__traits(compiles, ihnsdur += chnsdur)); |
|---|
| | 386 | static assert(__traits(compiles, hnsdur += ihnsdur)); |
|---|
| | 387 | static assert(!__traits(compiles, chnsdur += ihnsdur)); |
|---|
| | 388 | static assert(!__traits(compiles, ihnsdur += ihnsdur)); |
|---|
| | 389 | |
|---|
| | 390 | static assert(__traits(compiles, hnsdur += tdur)); |
|---|
| | 391 | static assert(!__traits(compiles, chnsdur += tdur)); |
|---|
| | 392 | static assert(!__traits(compiles, ihnsdur += tdur)); |
|---|
| | 393 | static assert(__traits(compiles, hnsdur += ctdur)); |
|---|
| | 394 | static assert(!__traits(compiles, chnsdur += ctdur)); |
|---|
| | 395 | static assert(!__traits(compiles, ihnsdur += ctdur)); |
|---|
| | 396 | static assert(__traits(compiles, hnsdur += itdur)); |
|---|
| | 397 | static assert(!__traits(compiles, chnsdur += itdur)); |
|---|
| | 398 | static assert(!__traits(compiles, ihnsdur += itdur)); |
|---|
| | 399 | |
|---|
| | 400 | static assert(__traits(compiles, hnsdur -= hnsdur)); |
|---|
| | 401 | static assert(!__traits(compiles, chnsdur -= hnsdur)); |
|---|
| | 402 | static assert(!__traits(compiles, ihnsdur -= hnsdur)); |
|---|
| | 403 | static assert(__traits(compiles, hnsdur -= chnsdur)); |
|---|
| | 404 | static assert(!__traits(compiles, chnsdur -= chnsdur)); |
|---|
| | 405 | static assert(!__traits(compiles, ihnsdur -= chnsdur)); |
|---|
| | 406 | static assert(__traits(compiles, hnsdur -= ihnsdur)); |
|---|
| | 407 | static assert(!__traits(compiles, chnsdur -= ihnsdur)); |
|---|
| | 408 | static assert(!__traits(compiles, ihnsdur -= ihnsdur)); |
|---|
| | 409 | |
|---|
| | 410 | static assert(__traits(compiles, hnsdur -= tdur)); |
|---|
| | 411 | static assert(!__traits(compiles, chnsdur -= tdur)); |
|---|
| | 412 | static assert(!__traits(compiles, ihnsdur -= tdur)); |
|---|
| | 413 | static assert(__traits(compiles, hnsdur -= ctdur)); |
|---|
| | 414 | static assert(!__traits(compiles, chnsdur -= ctdur)); |
|---|
| | 415 | static assert(!__traits(compiles, ihnsdur -= ctdur)); |
|---|
| | 416 | static assert(__traits(compiles, hnsdur -= itdur)); |
|---|
| | 417 | static assert(!__traits(compiles, chnsdur -= itdur)); |
|---|
| | 418 | static assert(!__traits(compiles, ihnsdur -= itdur)); |
|---|
| | 419 | } |
|---|
| | 420 | |
|---|
| | 421 | |
|---|
| | 422 | /++ |
|---|
| | 423 | The legal types of arithmetic for Duration using this operator overload are |
|---|
| | 424 | |
|---|
| | 425 | $(TABLE |
|---|
| | 426 | $(TR $(TD Duration) $(TD *) $(TD long) $(TD -->) $(TD Duration)) |
|---|
| | 427 | ) |
|---|
| | 428 | |
|---|
| | 429 | Params: |
|---|
| | 430 | value = The value to multiply this duration by. |
|---|
| | 431 | +/ |
|---|
| | 432 | Duration opBinary(string op)(long value) const pure nothrow |
|---|
| | 433 | if(op == "*") |
|---|
| | 434 | { |
|---|
| | 435 | return Duration(_hnsecs * value); |
|---|
| | 436 | } |
|---|
| | 437 | |
|---|
| | 438 | unittest |
|---|
| | 439 | { |
|---|
| | 440 | assert(Duration(5) * 7 == Duration(35)); |
|---|
| | 441 | assert(Duration(7) * 5 == Duration(35)); |
|---|
| | 442 | |
|---|
| | 443 | assert(Duration(5) * -7 == Duration(-35)); |
|---|
| | 444 | assert(Duration(7) * -5 == Duration(-35)); |
|---|
| | 445 | |
|---|
| | 446 | assert(Duration(-5) * 7 == Duration(-35)); |
|---|
| | 447 | assert(Duration(-7) * 5 == Duration(-35)); |
|---|
| | 448 | |
|---|
| | 449 | assert(Duration(-5) * -7 == Duration(35)); |
|---|
| | 450 | assert(Duration(-7) * -5 == Duration(35)); |
|---|
| | 451 | |
|---|
| | 452 | assert(Duration(5) * 0 == Duration(0)); |
|---|
| | 453 | assert(Duration(-5) * 0 == Duration(0)); |
|---|
| | 454 | |
|---|
| | 455 | auto dur = Duration(12); |
|---|
| | 456 | const cdur = Duration(12); |
|---|
| | 457 | immutable idur = Duration(12); |
|---|
| | 458 | static assert(__traits(compiles, dur * 12)); |
|---|
| | 459 | static assert(__traits(compiles, cdur * 12)); |
|---|
| | 460 | static assert(__traits(compiles, idur * 12)); |
|---|
| | 461 | } |
|---|
| | 462 | |
|---|
| | 463 | |
|---|
| | 464 | /++ |
|---|
| | 465 | The legal types of arithmetic for Duration using this operator overload are |
|---|
| | 466 | |
|---|
| | 467 | $(TABLE |
|---|
| | 468 | $(TR $(TD Duration) $(TD *) $(TD long) $(TD -->) $(TD Duration)) |
|---|
| | 469 | ) |
|---|
| | 470 | |
|---|
| | 471 | Params: |
|---|
| | 472 | value = The value to multiply this duration by. |
|---|
| | 473 | +/ |
|---|
| | 474 | /+ref+/ Duration opOpAssign(string op)(long value) pure nothrow |
|---|
| | 475 | if(op == "*") |
|---|
| | 476 | { |
|---|
| | 477 | _hnsecs *= value; |
|---|
| | 478 | |
|---|
| | 479 | return this; |
|---|
| | 480 | } |
|---|
| | 481 | |
|---|
| | 482 | unittest |
|---|
| | 483 | { |
|---|
| | 484 | static void testDur(Duration dur, long value, in Duration expected, size_t line = __LINE__) |
|---|
| | 485 | { |
|---|
| | 486 | if((dur *= value) != expected) |
|---|
| | 487 | throw new AssertError("op failed", __FILE__, line); |
|---|
| | 488 | |
|---|
| | 489 | if(dur != expected) |
|---|
| | 490 | throw new AssertError("op assign failed", __FILE__, line); |
|---|
| | 491 | } |
|---|
| | 492 | |
|---|
| | 493 | testDur(Duration(5), 7, Duration(35)); |
|---|
| | 494 | testDur(Duration(7), 5, Duration(35)); |
|---|
| | 495 | |
|---|
| | 496 | testDur(Duration(5), -7, Duration(-35)); |
|---|
| | 497 | testDur(Duration(7), -5, Duration(-35)); |
|---|
| | 498 | |
|---|
| | 499 | testDur(Duration(-5), 7, Duration(-35)); |
|---|
| | 500 | testDur(Duration(-7), 5, Duration(-35)); |
|---|
| | 501 | |
|---|
| | 502 | testDur(Duration(-5), -7, Duration(35)); |
|---|
| | 503 | testDur(Duration(-7), -5, Duration(35)); |
|---|
| | 504 | |
|---|
| | 505 | testDur(Duration(5), 0, Duration(0)); |
|---|
| | 506 | testDur(Duration(-5), 0, Duration(0)); |
|---|
| | 507 | |
|---|
| | 508 | auto dur = Duration(12); |
|---|
| | 509 | const cdur = Duration(12); |
|---|
| | 510 | immutable idur = Duration(12); |
|---|
| | 511 | static assert(__traits(compiles, dur *= 12)); |
|---|
| | 512 | static assert(!__traits(compiles, cdur *= 12)); |
|---|
| | 513 | static assert(!__traits(compiles, idur *= 12)); |
|---|
| | 514 | } |
|---|
| | 515 | |
|---|
| | 516 | |
|---|
| | 517 | /++ |
|---|
| | 518 | The legal types of arithmetic for Duration using this operator overload are |
|---|
| | 519 | |
|---|
| | 520 | $(TABLE |
|---|
| | 521 | $(TR $(TD Duration) $(TD /) $(TD long) $(TD -->) $(TD Duration)) |
|---|
| | 522 | ) |
|---|
| | 523 | |
|---|
| | 524 | Params: |
|---|
| | 525 | value = The value to divide from this duration. |
|---|
| | 526 | |
|---|
| | 527 | Throws: |
|---|
| | 528 | TimeException if an attempt to divide by 0 is made. |
|---|
| | 529 | +/ |
|---|
| | 530 | Duration opBinary(string op)(long value) pure const |
|---|
| | 531 | if(op == "/") |
|---|
| | 532 | { |
|---|
| | 533 | if(value == 0) |
|---|
| | 534 | throw new TimeException("Attempted division by 0."); |
|---|
| | 535 | |
|---|
| | 536 | return Duration(_hnsecs / value); |
|---|
| | 537 | } |
|---|
| | 538 | |
|---|
| | 539 | unittest |
|---|
| | 540 | { |
|---|
| | 541 | tAssertExThrown!TimeException((){Duration(5) / 0;}()); |
|---|
| | 542 | tAssertExThrown!TimeException((){Duration(-5) / 0;}()); |
|---|
| | 543 | |
|---|
| | 544 | assert(Duration(5) / 7 == Duration(0)); |
|---|
| | 545 | assert(Duration(7) / 5 == Duration(1)); |
|---|
| | 546 | |
|---|
| | 547 | assert(Duration(5) / -7 == Duration(0)); |
|---|
| | 548 | assert(Duration(7) / -5 == Duration(-1)); |
|---|
| | 549 | |
|---|
| | 550 | assert(Duration(-5) / 7 == Duration(0)); |
|---|
| | 551 | assert(Duration(-7) / 5 == Duration(-1)); |
|---|
| | 552 | |
|---|
| | 553 | assert(Duration(-5) / -7 == Duration(0)); |
|---|
| | 554 | assert(Duration(-7) / -5 == Duration(1)); |
|---|
| | 555 | |
|---|
| | 556 | auto dur = Duration(12); |
|---|
| | 557 | const cdur = Duration(12); |
|---|
| | 558 | immutable idur = Duration(12); |
|---|
| | 559 | static assert(__traits(compiles, dur / 12)); |
|---|
| | 560 | static assert(__traits(compiles, cdur / 12)); |
|---|
| | 561 | static assert(__traits(compiles, idur / 12)); |
|---|
| | 562 | } |
|---|
| | 563 | |
|---|
| | 564 | |
|---|
| | 565 | /++ |
|---|
| | 566 | The legal types of arithmetic for Duration using this operator overload are |
|---|
| | 567 | |
|---|
| | 568 | $(TABLE |
|---|
| | 569 | $(TR $(TD Duration) $(TD /) $(TD long) $(TD -->) $(TD Duration)) |
|---|
| | 570 | ) |
|---|
| | 571 | |
|---|
| | 572 | Params: |
|---|
| | 573 | value = The value to divide from this duration. |
|---|
| | 574 | |
|---|
| | 575 | Throws: |
|---|
| | 576 | TimeException if an attempt to divide by 0 is made. |
|---|
| | 577 | +/ |
|---|
| | 578 | /+ref+/ Duration opOpAssign(string op)(long value) pure |
|---|
| | 579 | if(op == "/") |
|---|
| | 580 | { |
|---|
| | 581 | if(value == 0) |
|---|
| | 582 | throw new TimeException("Attempted division by 0."); |
|---|
| | 583 | |
|---|
| | 584 | _hnsecs /= value; |
|---|
| | 585 | |
|---|
| | 586 | return this; |
|---|
| | 587 | } |
|---|
| | 588 | |
|---|
| | 589 | unittest |
|---|
| | 590 | { |
|---|
| | 591 | tAssertExThrown!TimeException((){Duration(5) /= 0;}()); |
|---|
| | 592 | tAssertExThrown!TimeException((){Duration(-5) /= 0;}()); |
|---|
| | 593 | |
|---|
| | 594 | static void testDur(Duration dur, long value, in Duration expected, size_t line = __LINE__) |
|---|
| | 595 | { |
|---|
| | 596 | if((dur /= value) != expected) |
|---|
| | 597 | throw new AssertError("op failed", __FILE__, line); |
|---|
| | 598 | |
|---|
| | 599 | if(dur != expected) |
|---|
| | 600 | throw new AssertError("op assign failed", __FILE__, line); |
|---|
| | 601 | } |
|---|
| | 602 | |
|---|
| | 603 | testDur(Duration(5), 7, Duration(0)); |
|---|
| | 604 | testDur(Duration(7), 5, Duration(1)); |
|---|
| | 605 | |
|---|
| | 606 | testDur(Duration(5), -7, Duration(0)); |
|---|
| | 607 | testDur(Duration(7), -5, Duration(-1)); |
|---|
| | 608 | |
|---|
| | 609 | testDur(Duration(-5), 7, Duration(0)); |
|---|
| | 610 | testDur(Duration(-7), 5, Duration(-1)); |
|---|
| | 611 | |
|---|
| | 612 | testDur(Duration(-5), -7, Duration(0)); |
|---|
| | 613 | testDur(Duration(-7), -5, Duration(1)); |
|---|
| | 614 | |
|---|
| | 615 | auto dur = Duration(12); |
|---|
| | 616 | const cdur = Duration(12); |
|---|
| | 617 | immutable idur = Duration(12); |
|---|
| | 618 | static assert(__traits(compiles, dur /= 12)); |
|---|
| | 619 | static assert(!__traits(compiles, cdur /= 12)); |
|---|
| | 620 | static assert(!__traits(compiles, idur /= 12)); |
|---|
| | 621 | } |
|---|
| | 622 | |
|---|
| | 623 | |
|---|
| | 624 | /++ |
|---|
| | 625 | Multiplies an integral value and a Duration. |
|---|
| | 626 | |
|---|
| | 627 | The legal types of arithmetic for Duration using this operator overload are |
|---|
| | 628 | |
|---|
| | 629 | $(TABLE |
|---|
| | 630 | $(TR $(TD long) $(TD *) $(TD Duration) $(TD -->) $(TD Duration)) |
|---|
| | 631 | ) |
|---|
| | 632 | |
|---|
| | 633 | Params: |
|---|
| | 634 | value = The number of units to multiply this duration by. |
|---|
| | 635 | +/ |
|---|
| | 636 | Duration opBinaryRight(string op)(long value) const pure nothrow |
|---|
| | 637 | if(op == "*") |
|---|
| | 638 | { |
|---|
| | 639 | return opBinary!op(value); |
|---|
| | 640 | } |
|---|
| | 641 | |
|---|
| | 642 | unittest |
|---|
| | 643 | { |
|---|
| | 644 | assert(5 * Duration(7) == Duration(35)); |
|---|
| | 645 | assert(7 * Duration(5) == Duration(35)); |
|---|
| | 646 | |
|---|
| | 647 | assert(5 * Duration(-7) == Duration(-35)); |
|---|
| | 648 | assert(7 * Duration(-5) == Duration(-35)); |
|---|
| | 649 | |
|---|
| | 650 | assert(-5 * Duration(7) == Duration(-35)); |
|---|
| | 651 | assert(-7 * Duration(5) == Duration(-35)); |
|---|
| | 652 | |
|---|
| | 653 | assert(-5 * Duration(-7) == Duration(35)); |
|---|
| | 654 | assert(-7 * Duration(-5) == Duration(35)); |
|---|
| | 655 | |
|---|
| | 656 | assert(0 * Duration(5) == Duration(0)); |
|---|
| | 657 | assert(0 * Duration(-5) == Duration(0)); |
|---|
| | 658 | |
|---|
| | 659 | const cdur = Duration(12); |
|---|
| | 660 | immutable idur = Duration(12); |
|---|
| | 661 | static assert(__traits(compiles, 12 * cdur)); |
|---|
| | 662 | static assert(__traits(compiles, 12 * idur)); |
|---|
| | 663 | } |
|---|
| | 664 | |
|---|
| | 665 | |
|---|
| | 666 | /++ |
|---|
| | 667 | Returns the negation of this Duration. |
|---|
| | 668 | +/ |
|---|
| | 669 | Duration opUnary(string op)() const pure nothrow |
|---|
| | 670 | if(op == "-") |
|---|
| | 671 | { |
|---|
| | 672 | return Duration(-_hnsecs); |
|---|
| | 673 | } |
|---|
| | 674 | |
|---|
| | 675 | unittest |
|---|
| | 676 | { |
|---|
| | 677 | assert(-Duration(7) == Duration(-7)); |
|---|
| | 678 | assert(-Duration(5) == Duration(-5)); |
|---|
| | 679 | assert(-Duration(-7) == Duration(7)); |
|---|
| | 680 | assert(-Duration(-5) == Duration(5)); |
|---|
| | 681 | assert(-Duration(0) == Duration(0)); |
|---|
| | 682 | |
|---|
| | 683 | const cdur = Duration(12); |
|---|
| | 684 | immutable idur = Duration(12); |
|---|
| | 685 | static assert(__traits(compiles, -cdur)); |
|---|
| | 686 | static assert(__traits(compiles, -idur)); |
|---|
| | 687 | } |
|---|
| | 688 | |
|---|
| | 689 | |
|---|
| | 690 | /++ |
|---|
| | 691 | Returns the number of the given units in the duration |
|---|
| | 692 | (minus the larger units). |
|---|
| | 693 | |
|---|
| | 694 | Examples: |
|---|
| | 695 | -------------------- |
|---|
| | 696 | assert(dur!"weeks"(12).get!"weeks"() == 12); |
|---|
| | 697 | assert(dur!"weeks"(12).get!"days"() == 0); |
|---|
| | 698 | |
|---|
| | 699 | assert(dur!"days"(13).get!"weeks"() == 1); |
|---|
| | 700 | assert(dur!"days"(13).get!"days"() == 6); |
|---|
| | 701 | |
|---|
| | 702 | assert(dur!"hours"(49).get!"days"() == 2); |
|---|
| | 703 | assert(dur!"hours"(49).get!"hours"() == 1); |
|---|
| | 704 | -------------------- |
|---|
| | 705 | +/ |
|---|
| | 706 | long get(string units)() const pure nothrow |
|---|
| | 707 | if(units == "weeks" || |
|---|
| | 708 | units == "days" || |
|---|
| | 709 | units == "hours" || |
|---|
| | 710 | units == "minutes" || |
|---|
| | 711 | units == "seconds") |
|---|
| | 712 | { |
|---|
| | 713 | static if(units == "weeks") |
|---|
| | 714 | return getUnitsFromHNSecs!"weeks"(_hnsecs); |
|---|
| | 715 | else |
|---|
| | 716 | { |
|---|
| | 717 | immutable hnsecs = removeUnitsFromHNSecs!(nextLargerTimeUnits!units)(_hnsecs); |
|---|
| | 718 | |
|---|
| | 719 | return getUnitsFromHNSecs!units(hnsecs); |
|---|
| | 720 | } |
|---|
| | 721 | } |
|---|
| | 722 | |
|---|
| | 723 | unittest |
|---|
| | 724 | { |
|---|
| | 725 | //Verify Examples. |
|---|
| | 726 | assert(dur!"weeks"(12).get!"weeks"() == 12); |
|---|
| | 727 | assert(dur!"weeks"(12).get!"days"() == 0); |
|---|
| | 728 | |
|---|
| | 729 | assert(dur!"days"(13).get!"weeks"() == 1); |
|---|
| | 730 | assert(dur!"days"(13).get!"days"() == 6); |
|---|
| | 731 | |
|---|
| | 732 | assert(dur!"hours"(49).get!"days"() == 2); |
|---|
| | 733 | assert(dur!"hours"(49).get!"hours"() == 1); |
|---|
| | 734 | |
|---|
| | 735 | const dur = Duration(12); |
|---|
| | 736 | const cdur = Duration(12); |
|---|
| | 737 | immutable idur = Duration(12); |
|---|
| | 738 | static assert(__traits(compiles, dur.get!"days"())); |
|---|
| | 739 | static assert(__traits(compiles, cdur.get!"days"())); |
|---|
| | 740 | static assert(__traits(compiles, idur.get!"days"())); |
|---|
| | 741 | } |
|---|
| | 742 | |
|---|
| | 743 | |
|---|
| | 744 | /++ |
|---|
| | 745 | Returns the number of weeks in the duration. |
|---|
| | 746 | |
|---|
| | 747 | Examples: |
|---|
| | 748 | -------------------- |
|---|
| | 749 | assert(dur!"weeks"(12).weeks == 12); |
|---|
| | 750 | assert(dur!"days"(13).weeks == 1); |
|---|
| | 751 | -------------------- |
|---|
| | 752 | +/ |
|---|
| | 753 | @property alias get!"weeks" weeks; |
|---|
| | 754 | |
|---|
| | 755 | unittest |
|---|
| | 756 | { |
|---|
| | 757 | //Verify Examples. |
|---|
| | 758 | assert(dur!"weeks"(12).weeks == 12); |
|---|
| | 759 | assert(dur!"days"(13).weeks == 1); |
|---|
| | 760 | |
|---|
| | 761 | const dur = Duration(12); |
|---|
| | 762 | const cdur = Duration(12); |
|---|
| | 763 | immutable idur = Duration(12); |
|---|
| | 764 | static assert(__traits(compiles, dur.weeks)); |
|---|
| | 765 | static assert(__traits(compiles, cdur.weeks)); |
|---|
| | 766 | static assert(__traits(compiles, idur.weeks)); |
|---|
| | 767 | } |
|---|
| | 768 | |
|---|
| | 769 | |
|---|
| | 770 | /++ |
|---|
| | 771 | Returns the number of days in the duration (minus the larger units). |
|---|
| | 772 | |
|---|
| | 773 | Examples: |
|---|
| | 774 | -------------------- |
|---|
| | 775 | assert(dur!"weeks"(12).days == 0); |
|---|
| | 776 | assert(dur!"days"(13).days == 6); |
|---|
| | 777 | assert(dur!"hours"(49).days == 2); |
|---|
| | 778 | -------------------- |
|---|
| | 779 | +/ |
|---|
| | 780 | @property alias get!"days" days; |
|---|
| | 781 | |
|---|
| | 782 | unittest |
|---|
| | 783 | { |
|---|
| | 784 | //Verify Examples. |
|---|
| | 785 | assert(dur!"weeks"(12).days == 0); |
|---|
| | 786 | assert(dur!"days"(13).days == 6); |
|---|
| | 787 | assert(dur!"hours"(49).days == 2); |
|---|
| | 788 | |
|---|
| | 789 | const dur = Duration(12); |
|---|
| | 790 | const cdur = Duration(12); |
|---|
| | 791 | immutable idur = Duration(12); |
|---|
| | 792 | static assert(__traits(compiles, dur.days)); |
|---|
| | 793 | static assert(__traits(compiles, cdur.days)); |
|---|
| | 794 | static assert(__traits(compiles, idur.days)); |
|---|
| | 795 | } |
|---|
| | 796 | |
|---|
| | 797 | |
|---|
| | 798 | /++ |
|---|
| | 799 | Returns the number of hours in the duration (minus the larger units). |
|---|
| | 800 | |
|---|
| | 801 | Examples: |
|---|
| | 802 | -------------------- |
|---|
| | 803 | assert(dur!"days"(8).hours == 0); |
|---|
| | 804 | assert(dur!"hours"(49).hours == 1); |
|---|
| | 805 | assert(dur!"minutes"(121).hours == 2); |
|---|
| | 806 | -------------------- |
|---|
| | 807 | +/ |
|---|
| | 808 | @property alias get!"hours" hours; |
|---|
| | 809 | |
|---|
| | 810 | unittest |
|---|
| | 811 | { |
|---|
| | 812 | //Verify Examples. |
|---|
| | 813 | assert(dur!"days"(8).hours == 0); |
|---|
| | 814 | assert(dur!"hours"(49).hours == 1); |
|---|
| | 815 | assert(dur!"minutes"(121).hours == 2); |
|---|
| | 816 | |
|---|
| | 817 | const dur = Duration(12); |
|---|
| | 818 | const cdur = Duration(12); |
|---|
| | 819 | immutable idur = Duration(12); |
|---|
| | 820 | static assert(__traits(compiles, dur.hours)); |
|---|
| | 821 | static assert(__traits(compiles, cdur.hours)); |
|---|
| | 822 | static assert(__traits(compiles, idur.hours)); |
|---|
| | 823 | } |
|---|
| | 824 | |
|---|
| | 825 | |
|---|
| | 826 | /++ |
|---|
| | 827 | Returns the number of minutes in the duration (minus the larger units). |
|---|
| | 828 | |
|---|
| | 829 | Examples: |
|---|
| | 830 | -------------------- |
|---|
| | 831 | assert(dur!"hours"(47).minutes == 0); |
|---|
| | 832 | assert(dur!"minutes"(127).minutes == 7); |
|---|
| | 833 | assert(dur!"seconds"(121).minutes == 2); |
|---|
| | 834 | -------------------- |
|---|
| | 835 | +/ |
|---|
| | 836 | @property alias get!"minutes" minutes; |
|---|
| | 837 | |
|---|
| | 838 | unittest |
|---|
| | 839 | { |
|---|
| | 840 | //Verify Examples. |
|---|
| | 841 | assert(dur!"hours"(47).minutes == 0); |
|---|
| | 842 | assert(dur!"minutes"(127).minutes == 7); |
|---|
| | 843 | assert(dur!"seconds"(121).minutes == 2); |
|---|
| | 844 | |
|---|
| | 845 | const dur = Duration(12); |
|---|
| | 846 | const cdur = Duration(12); |
|---|
| | 847 | immutable idur = Duration(12); |
|---|
| | 848 | static assert(__traits(compiles, dur.minutes)); |
|---|
| | 849 | static assert(__traits(compiles, cdur.minutes)); |
|---|
| | 850 | static assert(__traits(compiles, idur.minutes)); |
|---|
| | 851 | } |
|---|
| | 852 | |
|---|
| | 853 | |
|---|
| | 854 | /++ |
|---|
| | 855 | Returns the number of seconds in the duration (minus the larger units). |
|---|
| | 856 | |
|---|
| | 857 | Examples: |
|---|
| | 858 | -------------------- |
|---|
| | 859 | assert(dur!"minutes"(47).seconds == 0); |
|---|
| | 860 | assert(dur!"seconds"(127).seconds == 7); |
|---|
| | 861 | assert(dur!"msecs"(1217).seconds == 1); |
|---|
| | 862 | -------------------- |
|---|
| | 863 | +/ |
|---|
| | 864 | @property alias get!"seconds" seconds; |
|---|
| | 865 | |
|---|
| | 866 | unittest |
|---|
| | 867 | { |
|---|
| | 868 | //Verify Examples. |
|---|
| | 869 | assert(dur!"minutes"(47).seconds == 0); |
|---|
| | 870 | assert(dur!"seconds"(127).seconds == 7); |
|---|
| | 871 | assert(dur!"msecs"(1217).seconds == 1); |
|---|
| | 872 | |
|---|
| | 873 | const dur = Duration(12); |
|---|
| | 874 | const cdur = Duration(12); |
|---|
| | 875 | immutable idur = Duration(12); |
|---|
| | 876 | static assert(__traits(compiles, dur.seconds)); |
|---|
| | 877 | static assert(__traits(compiles, cdur.seconds)); |
|---|
| | 878 | static assert(__traits(compiles, idur.seconds)); |
|---|
| | 879 | } |
|---|
| | 880 | |
|---|
| | 881 | |
|---|
| | 882 | /++ |
|---|
| | 883 | Returns the fractional seconds passed the second. |
|---|
| | 884 | |
|---|
| | 885 | Examples: |
|---|
| | 886 | -------------------- |
|---|
| | 887 | assert(dur!"msecs"(1000).fracSec == FracSec.from!"msecs"(0)); |
|---|
| | 888 | assert(dur!"msecs"(1217).fracSec == FracSec.from!"msecs"(217)); |
|---|
| | 889 | assert(dur!"usecs"(43).fracSec == FracSec.from!"usecs"(43)); |
|---|
| | 890 | assert(dur!"hnsecs"(50_007).fracSec == FracSec.from!"hnsecs"(50_007)); |
|---|
| | 891 | -------------------- |
|---|
| | 892 | +/ |
|---|
| | 893 | @property FracSec fracSec() const pure nothrow |
|---|
| | 894 | { |
|---|
| | 895 | try |
|---|
| | 896 | { |
|---|
| | 897 | long hnsecs = _hnsecs; |
|---|
| | 898 | auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
|---|
| | 899 | |
|---|
| | 900 | if(hnsecs < 0) |
|---|
| | 901 | { |
|---|
| | 902 | hnsecs += convert!("hours", "hnsecs")(24); |
|---|
| | 903 | --days; |
|---|
| | 904 | } |
|---|
| | 905 | |
|---|
| | 906 | hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs); |
|---|
| | 907 | hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs); |
|---|
| | 908 | hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs); |
|---|
| | 909 | |
|---|
| | 910 | return FracSec.from!"hnsecs"(cast(int)hnsecs); |
|---|
| | 911 | } |
|---|
| | 912 | catch(Exception e) |
|---|
| | 913 | assert(0, "FracSec.from!\"hnsecs\"() threw."); |
|---|
| | 914 | } |
|---|
| | 915 | |
|---|
| | 916 | unittest |
|---|
| | 917 | { |
|---|
| | 918 | //Verify Examples. |
|---|
| | 919 | assert(dur!"msecs"(1000).fracSec == FracSec.from!"msecs"(0)); |
|---|
| | 920 | assert(dur!"msecs"(1217).fracSec == FracSec.from!"msecs"(217)); |
|---|
| | 921 | assert(dur!"usecs"(43).fracSec == FracSec.from!"usecs"(43)); |
|---|
| | 922 | assert(dur!"hnsecs"(50_007).fracSec == FracSec.from!"hnsecs"(50_007)); |
|---|
| | 923 | |
|---|
| | 924 | const dur = Duration(12); |
|---|
| | 925 | const cdur = Duration(12); |
|---|
| | 926 | immutable idur = Duration(12); |
|---|
| | 927 | static assert(__traits(compiles, dur.fracSec)); |
|---|
| | 928 | static assert(__traits(compiles, cdur.fracSec)); |
|---|
| | 929 | static assert(__traits(compiles, idur.fracSec)); |
|---|
| | 930 | } |
|---|
| | 931 | |
|---|
| | 932 | |
|---|
| | 933 | /++ |
|---|
| | 934 | Returns the total number of the given units in the duration. |
|---|
| | 935 | So, unlike $(D get()), it does not strip out the larger |
|---|
| | 936 | units. |
|---|
| | 937 | |
|---|
| | 938 | Examples: |
|---|
| | 939 | -------------------- |
|---|
| | 940 | assert(dur!"weeks"(12).total!"weeks"() == 12); |
|---|
| | 941 | assert(dur!"weeks"(12).total!"days"() == 84); |
|---|
| | 942 | |
|---|
| | 943 | assert(dur!"days"(13).total!"weeks"() == 1); |
|---|
| | 944 | assert(dur!"days"(13).total!"days"() == 13); |
|---|
| | 945 | |
|---|
| | 946 | assert(dur!"hours"(49).total!"days"() == 2); |
|---|
| | 947 | assert(dur!"hours"(49).total!"hours"() == 49); |
|---|
| | 948 | |
|---|
| | 949 | assert(dur!"nsecs"(2007).total!"hnsecs"() == 20); |
|---|
| | 950 | assert(dur!"nsecs"(2007).total!"nsecs"() == 2000); |
|---|
| | 951 | -------------------- |
|---|
| | 952 | +/ |
|---|
| | 953 | long total(string units)() const pure nothrow |
|---|
| | 954 | if(units == "weeks" || |
|---|
| | 955 | units == "days" || |
|---|
| | 956 | units == "hours" || |
|---|
| | 957 | units == "minutes" || |
|---|
| | 958 | units == "seconds" || |
|---|
| | 959 | units == "msecs" || |
|---|
| | 960 | units == "usecs" || |
|---|
| | 961 | units == "hnsecs" || |
|---|
| | 962 | units == "nsecs") |
|---|
| | 963 | { |
|---|
| | 964 | static if(units == "nsecs") |
|---|
| | 965 | return convert!("hnsecs", "nsecs")(_hnsecs); |
|---|
| | 966 | else |
|---|
| | 967 | return getUnitsFromHNSecs!units(_hnsecs); |
|---|
| | 968 | } |
|---|
| | 969 | |
|---|
| | 970 | unittest |
|---|
| | 971 | { |
|---|
| | 972 | //Verify Examples. |
|---|
| | 973 | assert(dur!"weeks"(12).total!"weeks"() == 12); |
|---|
| | 974 | assert(dur!"weeks"(12).total!"days"() == 84); |
|---|
| | 975 | |
|---|
| | 976 | assert(dur!"days"(13).total!"weeks"() == 1); |
|---|
| | 977 | assert(dur!"days"(13).total!"days"() == 13); |
|---|
| | 978 | |
|---|
| | 979 | assert(dur!"hours"(49).total!"days"() == 2); |
|---|
| | 980 | assert(dur!"hours"(49).total!"hours"() == 49); |
|---|
| | 981 | |
|---|
| | 982 | assert(dur!"nsecs"(2007).total!"hnsecs"() == 20); |
|---|
| | 983 | assert(dur!"nsecs"(2007).total!"nsecs"() == 2000); |
|---|
| | 984 | |
|---|
| | 985 | const dur = Duration(12); |
|---|
| | 986 | const cdur = Duration(12); |
|---|
| | 987 | immutable idur = Duration(12); |
|---|
| | 988 | static assert(__traits(compiles, dur.total!"days"())); |
|---|
| | 989 | static assert(__traits(compiles, cdur.total!"days"())); |
|---|
| | 990 | static assert(__traits(compiles, idur.total!"days"())); |
|---|
| | 991 | } |
|---|
| | 992 | |
|---|
| | 993 | |
|---|
| | 994 | /+ |
|---|
| | 995 | Converts this duration to a string. |
|---|
| | 996 | +/ |
|---|
| | 997 | //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't |
|---|
| | 998 | //have versions of toString() with extra modifiers, so we define one version |
|---|
| | 999 | //with modifiers and one without. |
|---|
| | 1000 | string toString() |
|---|
| | 1001 | { |
|---|
| | 1002 | return _toStringImpl(); |
|---|
| | 1003 | } |
|---|
| | 1004 | |
|---|
| | 1005 | |
|---|
| | 1006 | /++ |
|---|
| | 1007 | Converts this duration to a string. |
|---|
| | 1008 | +/ |
|---|
| | 1009 | //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't |
|---|
| | 1010 | //have versions of toString() with extra modifiers, so we define one version |
|---|
| | 1011 | //with modifiers and one without. |
|---|
| | 1012 | string toString() const pure nothrow |
|---|
| | 1013 | { |
|---|
| | 1014 | return _toStringImpl(); |
|---|
| | 1015 | } |
|---|
| | 1016 | |
|---|
| | 1017 | unittest |
|---|
| | 1018 | { |
|---|
| | 1019 | const dur = Duration(12); |
|---|
| | 1020 | const cdur = Duration(12); |
|---|
| | 1021 | immutable idur = Duration(12); |
|---|
| | 1022 | static assert(__traits(compiles, dur.toString())); |
|---|
| | 1023 | static assert(__traits(compiles, cdur.toString())); |
|---|
| | 1024 | static assert(__traits(compiles, idur.toString())); |
|---|
| | 1025 | } |
|---|
| | 1026 | |
|---|
| | 1027 | |
|---|
| | 1028 | @property bool isNegative() const pure nothrow |
|---|
| | 1029 | { |
|---|
| | 1030 | return _hnsecs < 0; |
|---|
| | 1031 | } |
|---|
| | 1032 | |
|---|
| | 1033 | unittest |
|---|
| | 1034 | { |
|---|
| | 1035 | assert(!Duration(100).isNegative); |
|---|
| | 1036 | assert(!Duration(1).isNegative); |
|---|
| | 1037 | assert(!Duration(0).isNegative); |
|---|
| | 1038 | assert(Duration(-1).isNegative); |
|---|
| | 1039 | assert(Duration(-100).isNegative); |
|---|
| | 1040 | } |
|---|
| | 1041 | |
|---|
| | 1042 | |
|---|
| | 1043 | private: |
|---|
| | 1044 | |
|---|
| | 1045 | /++ |
|---|
| | 1046 | Since we have two versions of toString(), we have _toStringImpl() |
|---|
| | 1047 | so that they can share implementations. |
|---|
| | 1048 | +/ |
|---|
| | 1049 | string _toStringImpl() const pure nothrow |
|---|
| | 1050 | { |
|---|
| | 1051 | long hnsecs = _hnsecs; |
|---|
| | 1052 | |
|---|
| | 1053 | immutable weeks = splitUnitsFromHNSecs!"weeks"(hnsecs); |
|---|
| | 1054 | immutable days = splitUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 1055 | immutable hours = splitUnitsFromHNSecs!"hours"(hnsecs); |
|---|
| | 1056 | immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs); |
|---|
| | 1057 | immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs); |
|---|
| | 1058 | immutable milliseconds = splitUnitsFromHNSecs!"msecs"(hnsecs); |
|---|
| | 1059 | immutable microseconds = splitUnitsFromHNSecs!"usecs"(hnsecs); |
|---|
| | 1060 | |
|---|
| | 1061 | try |
|---|
| | 1062 | { |
|---|
| | 1063 | auto totalUnits = 0; |
|---|
| | 1064 | |
|---|
| | 1065 | if(weeks != 0) |
|---|
| | 1066 | ++totalUnits; |
|---|
| | 1067 | if(days != 0) |
|---|
| | 1068 | ++totalUnits; |
|---|
| | 1069 | if(hours != 0) |
|---|
| | 1070 | ++totalUnits; |
|---|
| | 1071 | if(minutes != 0) |
|---|
| | 1072 | ++totalUnits; |
|---|
| | 1073 | if(seconds != 0) |
|---|
| | 1074 | ++totalUnits; |
|---|
| | 1075 | if(milliseconds != 0) |
|---|
| | 1076 | ++totalUnits; |
|---|
| | 1077 | if(microseconds != 0) |
|---|
| | 1078 | ++totalUnits; |
|---|
| | 1079 | if(hnsecs != 0) |
|---|
| | 1080 | ++totalUnits; |
|---|
| | 1081 | |
|---|
| | 1082 | string retval; |
|---|
| | 1083 | auto unitsUsed = 0; |
|---|
| | 1084 | |
|---|
| | 1085 | string unitsToPrint(string units, bool plural) |
|---|
| | 1086 | { |
|---|
| | 1087 | if(units == "seconds") |
|---|
| | 1088 | return plural ? "secs" : "sec"; |
|---|
| | 1089 | else if(units == "msecs") |
|---|
| | 1090 | return "ms"; |
|---|
| | 1091 | else if(units == "usecs") |
|---|
| | 1092 | return "ÃŽÅ’s"; |
|---|
| | 1093 | else |
|---|
| | 1094 | return plural ? units : units[0 .. $-1]; |
|---|
| | 1095 | } |
|---|
| | 1096 | |
|---|
| | 1097 | void addUnitStr(string units, long value) |
|---|
| | 1098 | { |
|---|
| | 1099 | if(value != 0) |
|---|
| | 1100 | { |
|---|
| | 1101 | auto utp = unitsToPrint(units, value != 1); |
|---|
| | 1102 | auto valueStr = numToString(value); |
|---|
| | 1103 | |
|---|
| | 1104 | if(unitsUsed == 0) |
|---|
| | 1105 | retval ~= valueStr ~ " " ~ utp; |
|---|
| | 1106 | else if(unitsUsed == totalUnits - 1) |
|---|
| | 1107 | { |
|---|
| | 1108 | if(totalUnits == 2) |
|---|
| | 1109 | retval ~= " and " ~ valueStr ~ " " ~ utp; |
|---|
| | 1110 | else |
|---|
| | 1111 | retval ~= ", and " ~ valueStr ~ " " ~ utp; |
|---|
| | 1112 | } |
|---|
| | 1113 | else |
|---|
| | 1114 | retval ~= ", " ~ valueStr ~ " " ~ utp; |
|---|
| | 1115 | |
|---|
| | 1116 | ++unitsUsed; |
|---|
| | 1117 | } |
|---|
| | 1118 | } |
|---|
| | 1119 | |
|---|
| | 1120 | addUnitStr("weeks", weeks); |
|---|
| | 1121 | addUnitStr("days", days); |
|---|
| | 1122 | addUnitStr("hours", hours); |
|---|
| | 1123 | addUnitStr("minutes", minutes); |
|---|
| | 1124 | addUnitStr("seconds", seconds); |
|---|
| | 1125 | addUnitStr("msecs", milliseconds); |
|---|
| | 1126 | addUnitStr("usecs", microseconds); |
|---|
| | 1127 | addUnitStr("hnsecs", hnsecs); |
|---|
| | 1128 | |
|---|
| | 1129 | if(retval.length == 0) |
|---|
| | 1130 | return "0 hnsecs"; |
|---|
| | 1131 | |
|---|
| | 1132 | return retval; |
|---|
| | 1133 | } |
|---|
| | 1134 | catch(Exception e) |
|---|
| | 1135 | assert(0, "Something threw when nothing can throw."); |
|---|
| | 1136 | } |
|---|
| | 1137 | |
|---|
| | 1138 | unittest |
|---|
| | 1139 | { |
|---|
| | 1140 | assert(Duration(0).toString() == "0 hnsecs"); |
|---|
| | 1141 | assert(Duration(1).toString() == "1 hnsec"); |
|---|
| | 1142 | assert(Duration(7).toString() == "7 hnsecs"); |
|---|
| | 1143 | assert(Duration(10).toString() == "1 ÃŽÅ’s"); |
|---|
| | 1144 | assert(Duration(20).toString() == "2 ÃŽÅ’s"); |
|---|
| | 1145 | assert(Duration(10_000).toString() == "1 ms"); |
|---|
| | 1146 | assert(Duration(20_000).toString() == "2 ms"); |
|---|
| | 1147 | assert(Duration(10_000_000).toString() == "1 sec"); |
|---|
| | 1148 | assert(Duration(20_000_000).toString() == "2 secs"); |
|---|
| | 1149 | assert(Duration(600_000_000).toString() == "1 minute"); |
|---|
| | 1150 | assert(Duration(1_200_000_000).toString() == "2 minutes"); |
|---|
| | 1151 | assert(Duration(36_000_000_000).toString() == "1 hour"); |
|---|
| | 1152 | assert(Duration(72_000_000_000).toString() == "2 hours"); |
|---|
| | 1153 | assert(Duration(864_000_000_000).toString() == "1 day"); |
|---|
| | 1154 | assert(Duration(1_728_000_000_000).toString() == "2 days"); |
|---|
| | 1155 | assert(Duration(6_048_000_000_000).toString() == "1 week"); |
|---|
| | 1156 | assert(Duration(12_096_000_000_000).toString() == "2 weeks"); |
|---|
| | 1157 | |
|---|
| | 1158 | assert(Duration(12).toString() == "1 ÃŽÅ’s and 2 hnsecs"); |
|---|
| | 1159 | assert(Duration(120_795).toString() == "12 ms, 79 ÃŽÅ’s, and 5 hnsecs"); |
|---|
| | 1160 | assert(Duration(12_096_020_900_003).toString() == "2 weeks, 2 secs, 90 ms, and 3 hnsecs"); |
|---|
| | 1161 | |
|---|
| | 1162 | assert(Duration(-1).toString() == "-1 hnsecs"); |
|---|
| | 1163 | assert(Duration(-7).toString() == "-7 hnsecs"); |
|---|
| | 1164 | assert(Duration(-10).toString() == "-1 ÃŽÅ’s"); |
|---|
| | 1165 | assert(Duration(-20).toString() == "-2 ÃŽÅ’s"); |
|---|
| | 1166 | assert(Duration(-10_000).toString() == "-1 ms"); |
|---|
| | 1167 | assert(Duration(-20_000).toString() == "-2 ms"); |
|---|
| | 1168 | assert(Duration(-10_000_000).toString() == "-1 secs"); |
|---|
| | 1169 | assert(Duration(-20_000_000).toString() == "-2 secs"); |
|---|
| | 1170 | assert(Duration(-600_000_000).toString() == "-1 minutes"); |
|---|
| | 1171 | assert(Duration(-1_200_000_000).toString() == "-2 minutes"); |
|---|
| | 1172 | assert(Duration(-36_000_000_000).toString() == "-1 hours"); |
|---|
| | 1173 | assert(Duration(-72_000_000_000).toString() == "-2 hours"); |
|---|
| | 1174 | assert(Duration(-864_000_000_000).toString() == "-1 days"); |
|---|
| | 1175 | assert(Duration(-1_728_000_000_000).toString() == "-2 days"); |
|---|
| | 1176 | assert(Duration(-6_048_000_000_000).toString() == "-1 weeks"); |
|---|
| | 1177 | assert(Duration(-12_096_000_000_000).toString() == "-2 weeks"); |
|---|
| | 1178 | |
|---|
| | 1179 | assert(Duration(-12).toString() == "-1 ÃŽÅ’s and -2 hnsecs"); |
|---|
| | 1180 | assert(Duration(-120_795).toString() == "-12 ms, -79 ÃŽÅ’s, and -5 hnsecs"); |
|---|
| | 1181 | assert(Duration(-12_096_020_900_003).toString() == "-2 weeks, -2 secs, -90 ms, and -3 hnsecs"); |
|---|
| | 1182 | } |
|---|
| | 1183 | |
|---|
| | 1184 | |
|---|
| | 1185 | /++ |
|---|
| | 1186 | Params: |
|---|
| | 1187 | hnsecs = The total number of hecto-nanoseconds in this duration. |
|---|
| | 1188 | +/ |
|---|
| | 1189 | @safe |
|---|
| | 1190 | this(long hnsecs) pure nothrow |
|---|
| | 1191 | { |
|---|
| | 1192 | _hnsecs = hnsecs; |
|---|
| | 1193 | } |
|---|
| | 1194 | |
|---|
| | 1195 | |
|---|
| | 1196 | long _hnsecs; |
|---|
| | 1197 | } |
|---|
| | 1198 | |
|---|
| | 1199 | |
|---|
| | 1200 | /++ |
|---|
| | 1201 | This allows you to construct a Duration from the given time units |
|---|
| | 1202 | with the given length. |
|---|
| | 1203 | |
|---|
| | 1204 | The possible values for units are "weeks", "days", "hours", "minutes", |
|---|
| | 1205 | "seconds", "msecs" (milliseconds), "usecs", (microseconds), |
|---|
| | 1206 | and "hnsecs" (hecto-nanoseconds, i.e. 100 ns). |
|---|
| | 1207 | |
|---|
| | 1208 | Params: |
|---|
| | 1209 | units = The time units of the duration (e.g. "days"). |
|---|
| | 1210 | length = The number of units in the duration. |
|---|
| | 1211 | +/ |
|---|
| | 1212 | @safe |
|---|
| | 1213 | Duration dur(string units)(long length) pure nothrow |
|---|
| | 1214 | if(units == "weeks" || |
|---|
| | 1215 | units == "days" || |
|---|
| | 1216 | units == "hours" || |
|---|
| | 1217 | units == "minutes" || |
|---|
| | 1218 | units == "seconds" || |
|---|
| | 1219 | units == "msecs" || |
|---|
| | 1220 | units == "usecs" || |
|---|
| | 1221 | units == "hnsecs" || |
|---|
| | 1222 | units == "nsecs") |
|---|
| | 1223 | { |
|---|
| | 1224 | return Duration(convert!(units, "hnsecs")(length)); |
|---|
| | 1225 | } |
|---|
| | 1226 | |
|---|
| | 1227 | unittest |
|---|
| | 1228 | { |
|---|
| | 1229 | assert(dur!"weeks"(7).total!"weeks"() == 7); |
|---|
| | 1230 | assert(dur!"days"(7).total!"days"() == 7); |
|---|
| | 1231 | assert(dur!"hours"(7).total!"hours"() == 7); |
|---|
| | 1232 | assert(dur!"minutes"(7).total!"minutes"() == 7); |
|---|
| | 1233 | assert(dur!"seconds"(7).total!"seconds"() == 7); |
|---|
| | 1234 | assert(dur!"msecs"(7).total!"msecs"() == 7); |
|---|
| | 1235 | assert(dur!"usecs"(7).total!"usecs"() == 7); |
|---|
| | 1236 | assert(dur!"hnsecs"(7).total!"hnsecs"() == 7); |
|---|
| | 1237 | assert(dur!"nsecs"(7).total!"nsecs"() == 0); |
|---|
| | 1238 | } |
|---|
| | 1239 | |
|---|
| | 1240 | |
|---|
| | 1241 | /++ |
|---|
| | 1242 | Duration in system clock ticks. |
|---|
| | 1243 | |
|---|
| | 1244 | This type maintains the most high precision ticks of system clock in each |
|---|
| | 1245 | environment. |
|---|
| | 1246 | +/ |
|---|
| | 1247 | struct TickDuration |
|---|
| | 1248 | { |
|---|
| | 1249 | @safe:// @@@BUG@@@ workaround for bug 4211 |
|---|
| | 1250 | |
|---|
| | 1251 | |
|---|
| | 1252 | /++ |
|---|
| | 1253 | The number of ticks that the system clock has in one second. |
|---|
| | 1254 | |
|---|
| | 1255 | Confirm that it is not 0, to examine whether you can use TickDuration. |
|---|
| | 1256 | +/ |
|---|
| | 1257 | static immutable long ticksPerSec; |
|---|
| | 1258 | |
|---|
| | 1259 | |
|---|
| | 1260 | /++ |
|---|
| | 1261 | TickDuration when application begins. |
|---|
| | 1262 | +/ |
|---|
| | 1263 | static immutable TickDuration appOrigin; |
|---|
| | 1264 | |
|---|
| | 1265 | |
|---|
| | 1266 | @trusted |
|---|
| | 1267 | shared static this() |
|---|
| | 1268 | { |
|---|
| | 1269 | version(Windows) |
|---|
| | 1270 | { |
|---|
| | 1271 | if(QueryPerformanceFrequency(cast(long*)&ticksPerSec) == 0) |
|---|
| | 1272 | ticksPerSec = 0; |
|---|
| | 1273 | } |
|---|
| | 1274 | else version(OSX) |
|---|
| | 1275 | { |
|---|
| | 1276 | static if(is(typeof(mach_absolute_time))) |
|---|
| | 1277 | { |
|---|
| | 1278 | mach_timebase_info_data_t info; |
|---|
| | 1279 | |
|---|
| | 1280 | if(mach_timebase_info(&info)) |
|---|
| | 1281 | ticksPerSec = 0; |
|---|
| | 1282 | else |
|---|
| | 1283 | ticksPerSec = (1_000_000_000 * info.numer) / info.denom; |
|---|
| | 1284 | } |
|---|
| | 1285 | else |
|---|
| | 1286 | ticksPerSec = 1_000_000; |
|---|
| | 1287 | } |
|---|
| | 1288 | else version(Posix) |
|---|
| | 1289 | { |
|---|
| | 1290 | static if(is(typeof(clock_gettime))) |
|---|
| | 1291 | { |
|---|
| | 1292 | timespec ts; |
|---|
| | 1293 | |
|---|
| | 1294 | if(clock_getres(CLOCK_MONOTONIC, &ts) != 0) |
|---|
| | 1295 | ticksPerSec = 0; |
|---|
| | 1296 | else |
|---|
| | 1297 | ticksPerSec = 1_000_000_000 / ts.tv_nsec; |
|---|
| | 1298 | } |
|---|
| | 1299 | else |
|---|
| | 1300 | ticksPerSec = 1_000_000; |
|---|
| | 1301 | } |
|---|
| | 1302 | |
|---|
| | 1303 | if(ticksPerSec != 0) |
|---|
| | 1304 | appOrigin = TickDuration.currSystemTick; |
|---|
| | 1305 | } |
|---|
| | 1306 | |
|---|
| | 1307 | unittest |
|---|
| | 1308 | { |
|---|
| | 1309 | assert(ticksPerSec); |
|---|
| | 1310 | } |
|---|
| | 1311 | |
|---|
| | 1312 | |
|---|
| | 1313 | /++ |
|---|
| | 1314 | The number of ticks. |
|---|
| | 1315 | |
|---|
| | 1316 | You can convert this length into number of seconds by dividing it |
|---|
| | 1317 | by ticksPerSec. |
|---|
| | 1318 | +/ |
|---|
| | 1319 | long length; |
|---|
| | 1320 | |
|---|
| | 1321 | |
|---|
| | 1322 | /++ |
|---|
| | 1323 | Converts TickDuration to the given units as an integral value. |
|---|
| | 1324 | |
|---|
| | 1325 | Params: |
|---|
| | 1326 | units = The units to convert to. "seconds" and smaller only. |
|---|
| | 1327 | T = The integral type to convert to. |
|---|
| | 1328 | +/ |
|---|
| | 1329 | T to(string units, T)() const pure nothrow |
|---|
| | 1330 | if((units == "seconds" || |
|---|
| | 1331 | units == "msecs" || |
|---|
| | 1332 | units == "usecs" || |
|---|
| | 1333 | units == "hnsecs" || |
|---|
| | 1334 | units == "nsecs") && |
|---|
| | 1335 | (__traits(isIntegral, T) && T.sizeof >= 4)) |
|---|
| | 1336 | { |
|---|
| | 1337 | enum unitsPerSec = convert!("seconds", units)(1); |
|---|
| | 1338 | |
|---|
| | 1339 | if(ticksPerSec >= unitsPerSec) |
|---|
| | 1340 | return cast(T)(length / (ticksPerSec / unitsPerSec)); |
|---|
| | 1341 | else |
|---|
| | 1342 | return cast(T)(length * (unitsPerSec / ticksPerSec)); |
|---|
| | 1343 | } |
|---|
| | 1344 | |
|---|
| | 1345 | |
|---|
| | 1346 | /++ |
|---|
| | 1347 | Converts TickDuration to the given units as a floating point value. |
|---|
| | 1348 | |
|---|
| | 1349 | Params: |
|---|
| | 1350 | units = The units to convert to. "seconds" and smaller only. |
|---|
| | 1351 | T = The floating point type to convert to. |
|---|
| | 1352 | +/ |
|---|
| | 1353 | T to(string units, T)() const pure nothrow |
|---|
| | 1354 | if((units == "seconds" || |
|---|
| | 1355 | units == "msecs" || |
|---|
| | 1356 | units == "usecs" || |
|---|
| | 1357 | units == "hnsecs" || |
|---|
| | 1358 | units == "nsecs") && |
|---|
| | 1359 | __traits(isFloating, T)) |
|---|
| | 1360 | { |
|---|
| | 1361 | static if(units == "seconds") |
|---|
| | 1362 | { |
|---|
| | 1363 | //@@@BUG@@@ workaround for bug 4689 |
|---|
| | 1364 | long t = ticksPerSec; |
|---|
| | 1365 | |
|---|
| | 1366 | return length / cast(T)t; |
|---|
| | 1460 | |
|---|
| | 1461 | if(ticksPerSec >= 1) |
|---|
| | 1462 | assert(TickDuration.from!"seconds"(7).seconds == 7); |
|---|
| | 1463 | } |
|---|
| | 1464 | |
|---|
| | 1465 | //test from!"msecs"(). |
|---|
| | 1466 | unittest |
|---|
| | 1467 | { |
|---|
| | 1468 | auto t = TickDuration.from!"msecs"(1_000_000); |
|---|
| | 1469 | assert(t.msecs == 1_000_000); |
|---|
| | 1470 | t = TickDuration.from!"msecs"(2_000_000); |
|---|
| | 1471 | assert(t.msecs == 2_000_000); |
|---|
| | 1472 | |
|---|
| | 1473 | if(ticksPerSec >= 1000) |
|---|
| | 1474 | { |
|---|
| | 1475 | t.length -= 1; |
|---|
| | 1476 | assert(t.msecs == 1_999_999); |
|---|
| | 1477 | } |
|---|
| | 1478 | |
|---|
| | 1479 | if(ticksPerSec >= 1_000) |
|---|
| | 1480 | assert(TickDuration.from!"msecs"(7).msecs == 7); |
|---|
| | 1481 | } |
|---|
| | 1482 | |
|---|
| | 1483 | //test from!"usecs"(). |
|---|
| | 1484 | unittest |
|---|
| | 1485 | { |
|---|
| | 1486 | auto t = TickDuration.from!"usecs"(1_000_000); |
|---|
| | 1487 | assert(t.usecs == 1_000_000); |
|---|
| | 1488 | t = TickDuration.from!"usecs"(2_000_000); |
|---|
| | 1489 | assert(t.usecs == 2_000_000); |
|---|
| | 1490 | |
|---|
| | 1491 | if(ticksPerSec >= 1_000_000) |
|---|
| | 1492 | { |
|---|
| | 1493 | t.length -= 1; |
|---|
| | 1494 | assert(t.usecs == 1_999_999); |
|---|
| | 1495 | } |
|---|
| | 1496 | |
|---|
| | 1497 | if(ticksPerSec >= 1_000_000) |
|---|
| | 1498 | assert(TickDuration.from!"usecs"(7).usecs == 7); |
|---|
| | 1499 | } |
|---|
| | 1500 | |
|---|
| | 1501 | //test from!"hnsecs"(). |
|---|
| | 1502 | unittest |
|---|
| | 1503 | { |
|---|
| | 1504 | auto t = TickDuration.from!"hnsecs"(10_000_000); |
|---|
| | 1505 | assert(t.hnsecs == 10_000_000); |
|---|
| | 1506 | t = TickDuration.from!"hnsecs"(20_000_000); |
|---|
| | 1507 | assert(t.hnsecs == 20_000_000); |
|---|
| | 1508 | |
|---|
| | 1509 | if(ticksPerSec == 1_000_000) |
|---|
| | 1510 | { |
|---|
| | 1511 | t.length -= 1; |
|---|
| | 1512 | assert(t.hnsecs == 19999990); |
|---|
| | 1513 | assert(TickDuration.from!"hnsecs"(70).hnsecs == 70); |
|---|
| | 1514 | assert(TickDuration.from!"hnsecs"(7).hnsecs == 0); |
|---|
| | 1515 | } |
|---|
| | 1516 | |
|---|
| | 1517 | if(ticksPerSec >= 10_000_000) |
|---|
| | 1518 | { |
|---|
| | 1519 | t.length -= 1; |
|---|
| | 1520 | assert(t.hnsecs == 19999999); |
|---|
| | 1521 | assert(TickDuration.from!"hnsecs"(70).hnsecs == 70); |
|---|
| | 1522 | assert(TickDuration.from!"hnsecs"(7).hnsecs == 7); |
|---|
| | 1523 | } |
|---|
| | 1524 | } |
|---|
| | 1525 | |
|---|
| | 1526 | //test from!"nsecs"(). |
|---|
| | 1527 | unittest |
|---|
| | 1528 | { |
|---|
| | 1529 | auto t = TickDuration.from!"nsecs"(1_000_000_000); |
|---|
| | 1530 | assert(t.nsecs == 1_000_000_000); |
|---|
| | 1531 | t = TickDuration.from!"nsecs"(2_000_000_000); |
|---|
| | 1532 | assert(t.nsecs == 2_000_000_000); |
|---|
| | 1533 | |
|---|
| | 1534 | if(ticksPerSec == 1_000_000) |
|---|
| | 1535 | { |
|---|
| | 1536 | t.length -= 1; |
|---|
| | 1537 | assert(t.nsecs == 1999999000); |
|---|
| | 1538 | } |
|---|
| | 1539 | |
|---|
| | 1540 | if(ticksPerSec >= 1_000_000_000) |
|---|
| | 1541 | { |
|---|
| | 1542 | t.length -= 1; |
|---|
| | 1543 | assert(t.nsecs == 1999999999); |
|---|
| | 1544 | } |
|---|
| | 1545 | } |
|---|
| | 1546 | |
|---|
| | 1547 | |
|---|
| | 1548 | /++ |
|---|
| | 1549 | Returns a Duration with the same number of hnsecs as this TickDuration. |
|---|
| | 1550 | +/ |
|---|
| | 1551 | Duration opCast(T)() const pure nothrow |
|---|
| | 1552 | if(is(T == Duration)) |
|---|
| | 1553 | { |
|---|
| | 1554 | return Duration(hnsecs); |
|---|
| | 1555 | } |
|---|
| | 1556 | |
|---|
| | 1557 | unittest |
|---|
| | 1558 | { |
|---|
| | 1559 | auto t = TickDuration.from!"hnsecs"(10000000); |
|---|
| | 1560 | assert(cast(Duration)t == Duration(10000000)); |
|---|
| | 1561 | t = TickDuration.from!"hnsecs"(20000000); |
|---|
| | 1562 | assert(cast(Duration)t == Duration(20000000)); |
|---|
| | 1563 | |
|---|
| | 1564 | if(ticksPerSec == 1_000_000) |
|---|
| | 1565 | { |
|---|
| | 1566 | t.length -= 1; |
|---|
| | 1567 | assert(cast(Duration)t == Duration(19999990)); |
|---|
| | 1568 | assert(cast(Duration)TickDuration.from!"hnsecs"(70) == Duration(70)); |
|---|
| | 1569 | assert(cast(Duration)TickDuration.from!"hnsecs"(7) == Duration(0)); |
|---|
| | 1570 | } |
|---|
| | 1571 | |
|---|
| | 1572 | if(ticksPerSec >= 10_000_000) |
|---|
| | 1573 | { |
|---|
| | 1574 | t.length -= 1; |
|---|
| | 1575 | assert(cast(Duration)t == Duration(19999999)); |
|---|
| | 1576 | assert(cast(Duration)TickDuration.from!"hnsecs"(70) == Duration(70)); |
|---|
| | 1577 | assert(cast(Duration)TickDuration.from!"hnsecs"(7) == Duration(7)); |
|---|
| | 1578 | } |
|---|
| | 1579 | } |
|---|
| | 1580 | |
|---|
| | 1581 | |
|---|
| | 1582 | /++ |
|---|
| | 1583 | operator overloading "-=, +=" |
|---|
| | 1584 | |
|---|
| | 1585 | BUG: This should be return "ref TickDuration", but bug2460 prevents that. |
|---|
| | 1586 | +/ |
|---|
| | 1587 | /+ref TickDuration+/ void opOpAssign(string op)(in TickDuration rhs) pure nothrow |
|---|
| | 1588 | if(op == "+" || op == "-") |
|---|
| | 1589 | { |
|---|
| | 1590 | mixin("length " ~ op ~ "= rhs.length;"); |
|---|
| | 1591 | //return this; |
|---|
| | 1592 | } |
|---|
| | 1593 | |
|---|
| | 1594 | unittest |
|---|
| | 1595 | { |
|---|
| | 1596 | TickDuration a = TickDuration.currSystemTick, b = TickDuration.currSystemTick; |
|---|
| | 1597 | a += TickDuration.currSystemTick; |
|---|
| | 1598 | assert(a.to!("seconds", real)() >= 0); |
|---|
| | 1599 | b -= TickDuration.currSystemTick; |
|---|
| | 1600 | assert(b.to!("seconds", real)() <= 0); |
|---|
| | 1601 | } |
|---|
| | 1602 | |
|---|
| | 1603 | |
|---|
| | 1604 | /++ |
|---|
| | 1605 | operator overloading "-, +" |
|---|
| | 1606 | +/ |
|---|
| | 1607 | TickDuration opBinary(string op)(in TickDuration rhs) const pure nothrow |
|---|
| | 1608 | if(op == "-" || op == "+") |
|---|
| | 1609 | { |
|---|
| | 1610 | return TickDuration(mixin("length " ~ op ~ " rhs.length")); |
|---|
| | 1611 | } |
|---|
| | 1612 | |
|---|
| | 1613 | unittest |
|---|
| | 1614 | { |
|---|
| | 1615 | auto a = TickDuration.currSystemTick; |
|---|
| | 1616 | auto b = TickDuration.currSystemTick; |
|---|
| | 1617 | assert((a + b).to!("seconds", real) > 0); |
|---|
| | 1618 | assert((a - b).to!("seconds", real) <= 0); |
|---|
| | 1619 | } |
|---|
| | 1620 | |
|---|
| | 1621 | |
|---|
| | 1622 | /++ |
|---|
| | 1623 | Returns the negation of this TickDuration. |
|---|
| | 1624 | +/ |
|---|
| | 1625 | TickDuration opUnary(string op)() const pure nothrow |
|---|
| | 1626 | if(op == "-") |
|---|
| | 1627 | { |
|---|
| | 1628 | return TickDuration(-length); |
|---|
| | 1629 | } |
|---|
| | 1630 | |
|---|
| | 1631 | unittest |
|---|
| | 1632 | { |
|---|
| | 1633 | assert(-TickDuration(7) == TickDuration(-7)); |
|---|
| | 1634 | assert(-TickDuration(5) == TickDuration(-5)); |
|---|
| | 1635 | assert(-TickDuration(-7) == TickDuration(7)); |
|---|
| | 1636 | assert(-TickDuration(-5) == TickDuration(5)); |
|---|
| | 1637 | assert(-TickDuration(0) == TickDuration(0)); |
|---|
| | 1638 | |
|---|
| | 1639 | const cdur = TickDuration(12); |
|---|
| | 1640 | immutable idur = TickDuration(12); |
|---|
| | 1641 | static assert(__traits(compiles, -cdur)); |
|---|
| | 1642 | static assert(__traits(compiles, -idur)); |
|---|
| | 1643 | } |
|---|
| | 1644 | |
|---|
| | 1645 | |
|---|
| | 1646 | /++ |
|---|
| | 1647 | operator overloading "==" |
|---|
| | 1648 | +/ |
|---|
| | 1649 | bool opEquals(ref const TickDuration rhs) const pure nothrow |
|---|
| | 1650 | { |
|---|
| | 1651 | return length == rhs.length; |
|---|
| | 1652 | } |
|---|
| | 1653 | |
|---|
| | 1654 | unittest |
|---|
| | 1655 | { |
|---|
| | 1656 | auto t1 = TickDuration.currSystemTick; |
|---|
| | 1657 | assert(t1 == t1); |
|---|
| | 1658 | } |
|---|
| | 1659 | |
|---|
| | 1660 | |
|---|
| | 1661 | /++ |
|---|
| | 1662 | operator overloading "<, >, <=, >=" |
|---|
| | 1663 | +/ |
|---|
| | 1664 | int opCmp(ref const TickDuration rhs) const pure nothrow |
|---|
| | 1665 | { |
|---|
| | 1666 | return length < rhs.length ? -1 : (length == rhs.length ? 0 : 1); |
|---|
| | 1667 | } |
|---|
| | 1668 | |
|---|
| | 1669 | unittest |
|---|
| | 1670 | { |
|---|
| | 1671 | auto t1 = TickDuration.currSystemTick; |
|---|
| | 1672 | auto t2 = TickDuration.currSystemTick; |
|---|
| | 1673 | assert(t1 <= t2); |
|---|
| | 1674 | assert(t2 >= t1); |
|---|
| | 1675 | } |
|---|
| | 1676 | |
|---|
| | 1677 | |
|---|
| | 1678 | /++ |
|---|
| | 1679 | The legal types of arithmetic for TickDuration using this operator overload are |
|---|
| | 1680 | |
|---|
| | 1681 | $(TABLE |
|---|
| | 1682 | $(TR $(TD TickDuration) $(TD *) $(TD long) $(TD -->) $(TD TickDuration)) |
|---|
| | 1683 | $(TR $(TD TickDuration) $(TD *) $(TD floating point) $(TD -->) $(TD TickDuration)) |
|---|
| | 1684 | ) |
|---|
| | 1685 | |
|---|
| | 1686 | Params: |
|---|
| | 1687 | value = The value to divide from this duration. |
|---|
| | 1688 | +/ |
|---|
| | 1689 | void opOpAssign(string op, T)(T value) pure nothrow |
|---|
| | 1690 | if(op == "*" && |
|---|
| | 1691 | (__traits(isIntegral, T) || __traits(isFloating, T))) |
|---|
| | 1692 | { |
|---|
| | 1693 | length *= value; |
|---|
| | 1694 | } |
|---|
| | 1695 | |
|---|
| | 1696 | unittest |
|---|
| | 1697 | { |
|---|
| | 1698 | immutable t = TickDuration.currSystemTick; |
|---|
| | 1699 | TickDuration t1 = t, t2 = t; |
|---|
| | 1700 | t1 /= 2; |
|---|
| | 1701 | assert(t1 < t); |
|---|
| | 1702 | t2 /= 2.1L; |
|---|
| | 1703 | assert(t2 < t1); |
|---|
| | 1704 | } |
|---|
| | 1705 | |
|---|
| | 1706 | |
|---|
| | 1707 | /++ |
|---|
| | 1708 | The legal types of arithmetic for TickDuration using this operator overload are |
|---|
| | 1709 | |
|---|
| | 1710 | $(TABLE |
|---|
| | 1711 | $(TR $(TD TickDuration) $(TD /) $(TD long) $(TD -->) $(TD TickDuration)) |
|---|
| | 1712 | $(TR $(TD TickDuration) $(TD /) $(TD floating point) $(TD -->) $(TD TickDuration)) |
|---|
| | 1713 | ) |
|---|
| | 1714 | |
|---|
| | 1715 | Params: |
|---|
| | 1716 | value = The value to divide from this duration. |
|---|
| | 1717 | |
|---|
| | 1718 | Throws: |
|---|
| | 1719 | TimeException if an attempt to divide by 0 is made. |
|---|
| | 1720 | +/ |
|---|
| | 1721 | void opOpAssign(string op, T)(T value) pure |
|---|
| | 1722 | if(op == "/" && |
|---|
| | 1723 | (__traits(isIntegral, T) || __traits(isFloating, T))) |
|---|
| | 1724 | { |
|---|
| | 1725 | if(value == 0) |
|---|
| | 1726 | throw new TimeException("Attempted division by 0."); |
|---|
| | 1727 | |
|---|
| | 1728 | length /= value; |
|---|
| | 1729 | } |
|---|
| | 1730 | |
|---|
| | 1731 | unittest |
|---|
| | 1732 | { |
|---|
| | 1733 | immutable t = TickDuration.currSystemTick; |
|---|
| | 1734 | TickDuration t1 = t, t2 = t; |
|---|
| | 1735 | t1 /= 2; |
|---|
| | 1736 | assert(t1 < t); |
|---|
| | 1737 | t2 /= 2.1L; |
|---|
| | 1738 | assert(t2 < t1); |
|---|
| | 1739 | } |
|---|
| | 1740 | |
|---|
| | 1741 | |
|---|
| | 1742 | /++ |
|---|
| | 1743 | The legal types of arithmetic for TickDuration using this operator overload are |
|---|
| | 1744 | |
|---|
| | 1745 | $(TABLE |
|---|
| | 1746 | $(TR $(TD TickDuration) $(TD *) $(TD long) $(TD -->) $(TD TickDuration)) |
|---|
| | 1747 | $(TR $(TD TickDuration) $(TD *) $(TD floating point) $(TD -->) $(TD TickDuration)) |
|---|
| | 1748 | ) |
|---|
| | 1749 | |
|---|
| | 1750 | Params: |
|---|
| | 1751 | value = The value to divide from this duration. |
|---|
| | 1752 | +/ |
|---|
| | 1753 | TickDuration opBinary(string op, T)(T value) const pure nothrow |
|---|
| | 1754 | if(op == "*" && |
|---|
| | 1755 | (__traits(isIntegral, T) || __traits(isFloating, T))) |
|---|
| | 1756 | { |
|---|
| | 1757 | return TickDuration(cast(long)(length * value)); |
|---|
| | 1758 | } |
|---|
| | 1759 | |
|---|
| | 1760 | unittest |
|---|
| | 1761 | { |
|---|
| | 1762 | auto t = TickDuration.currSystemTick; |
|---|
| | 1763 | auto t2 = t*2; |
|---|
| | 1764 | assert(t < t2); |
|---|
| | 1765 | assert(t*3.5 > t2); |
|---|
| | 1766 | } |
|---|
| | 1767 | |
|---|
| | 1768 | |
|---|
| | 1769 | /++ |
|---|
| | 1770 | The legal types of arithmetic for TickDuration using this operator overload are |
|---|
| | 1771 | |
|---|
| | 1772 | $(TABLE |
|---|
| | 1773 | $(TR $(TD TickDuration) $(TD /) $(TD long) $(TD -->) $(TD TickDuration)) |
|---|
| | 1774 | $(TR $(TD TickDuration) $(TD /) $(TD floating point) $(TD -->) $(TD TickDuration)) |
|---|
| | 1775 | ) |
|---|
| | 1776 | |
|---|
| | 1777 | Params: |
|---|
| | 1778 | value = The value to divide from this duration. |
|---|
| | 1779 | |
|---|
| | 1780 | Throws: |
|---|
| | 1781 | TimeException if an attempt to divide by 0 is made. |
|---|
| | 1782 | +/ |
|---|
| | 1783 | TickDuration opBinary(string op, T)(T value) const pure |
|---|
| | 1784 | if(op == "/" && |
|---|
| | 1785 | (__traits(isIntegral, T) || __traits(isFloating, T))) |
|---|
| | 1786 | { |
|---|
| | 1787 | if(value == 0) |
|---|
| | 1788 | throw new TimeException("Attempted division by 0."); |
|---|
| | 1789 | |
|---|
| | 1790 | return TickDuration(cast(long)(length / value)); |
|---|
| | 1791 | } |
|---|
| | 1792 | |
|---|
| | 1793 | |
|---|
| | 1794 | /++ |
|---|
| | 1795 | Params: |
|---|
| | 1796 | ticks = The number of ticks in the TickDuration. |
|---|
| | 1797 | +/ |
|---|
| | 1798 | this(long ticks) pure nothrow |
|---|
| | 1799 | { |
|---|
| | 1800 | this.length = ticks; |
|---|
| | 1801 | } |
|---|
| | 1802 | |
|---|
| | 1803 | |
|---|
| | 1804 | /++ |
|---|
| | 1805 | The current system tick. The number of ticks per second varies from |
|---|
| | 1806 | system to system. This uses a monotonic clock, so it's intended for |
|---|
| | 1807 | precision timing by comparing relative time values, not for getting |
|---|
| | 1808 | the current system time. |
|---|
| | 1809 | |
|---|
| | 1810 | On Windows, QueryPerformanceCounter() is used. On Mac OS X, |
|---|
| | 1811 | mach_absolute_time() is used, while on other Posix systems, |
|---|
| | 1812 | clock_gettime() is used. If mach_absolute_time() or clock_gettime() |
|---|
| | 1813 | is unavailable, then Posix systems use gettimeofday(), which |
|---|
| | 1814 | unfortunately, is not monotonic, but without |
|---|
| | 1815 | mach_absolute_time()/clock_gettime() available, gettimeofday() is the |
|---|
| | 1816 | the best that you can do. |
|---|
| | 1817 | |
|---|
| | 1818 | Warning: |
|---|
| | 1819 | On some systems, the monotonic clock may stop counting when |
|---|
| | 1820 | the computer goes to sleep or hibernates. So, the monotonic |
|---|
| | 1821 | clock could be off if that occurs. This is known to happen |
|---|
| | 1822 | on Mac OS X. It has not been tested whether it occurs on |
|---|
| | 1823 | either Windows or on Linux. |
|---|
| | 1824 | |
|---|
| | 1825 | Throws: |
|---|
| | 1826 | TimeException if it fails to get the time. |
|---|
| | 1827 | +/ |
|---|
| | 1828 | @trusted |
|---|
| | 1829 | static @property TickDuration currSystemTick() |
|---|
| | 1830 | { |
|---|
| | 1831 | version(Windows) |
|---|
| | 1832 | { |
|---|
| | 1833 | ulong ticks; |
|---|
| | 1834 | |
|---|
| | 1835 | if(QueryPerformanceCounter(cast(long*)&ticks) == 0) |
|---|
| | 1836 | throw new TimeException(sysErrorString(GetLastError())); |
|---|
| | 1837 | |
|---|
| | 1838 | return TickDuration(ticks); |
|---|
| | 1839 | } |
|---|
| | 1840 | else version(OSX) |
|---|
| | 1841 | { |
|---|
| | 1842 | static if(is(typeof(mach_absolute_time))) |
|---|
| | 1843 | return TickDuration(cast(long)mach_absolute_time()); |
|---|
| | 1844 | else |
|---|
| | 1845 | { |
|---|
| | 1846 | timeval tv; |
|---|
| | 1847 | if(gettimeofday(&tv, null) != 0) |
|---|
| | 1848 | throw new TimeException("Failed in gettimeofday()."); |
|---|
| | 1849 | |
|---|
| | 1850 | return TickDuration(tv.tv_sec * TickDuration.ticksPerSec + |
|---|
| | 1851 | tv.tv_usec * TickDuration.ticksPerSec / 1000 / 1000); |
|---|
| | 1852 | } |
|---|
| | 1853 | } |
|---|
| | 1854 | else version(Posix) |
|---|
| | 1855 | { |
|---|
| | 1856 | static if(is(typeof(clock_gettime))) |
|---|
| | 1857 | { |
|---|
| | 1858 | timespec ts; |
|---|
| | 1859 | |
|---|
| | 1860 | if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) |
|---|
| | 1861 | throw new TimeException("Failed in clock_gettime()."); |
|---|
| | 1862 | |
|---|
| | 1863 | return TickDuration(ts.tv_sec * TickDuration.ticksPerSec + |
|---|
| | 1864 | ts.tv_nsec * TickDuration.ticksPerSec / 1000 / 1000 / 1000); |
|---|
| | 1865 | } |
|---|
| | 1866 | else |
|---|
| | 1867 | { |
|---|
| | 1868 | timeval tv; |
|---|
| | 1869 | if(gettimeofday(&tv, null) != 0) |
|---|
| | 1870 | throw new TimeException("Failed in gettimeofday()."); |
|---|
| | 1871 | |
|---|
| | 1872 | return TickDuration(tv.tv_sec * TickDuration.ticksPerSec + |
|---|
| | 1873 | tv.tv_usec * TickDuration.ticksPerSec / 1000 / 1000); |
|---|
| | 1874 | } |
|---|
| | 1875 | } |
|---|
| | 1876 | } |
|---|
| | 1877 | |
|---|
| | 1878 | @trusted |
|---|
| | 1879 | unittest |
|---|
| | 1880 | { |
|---|
| | 1881 | auto t = TickDuration.currSystemTick; |
|---|
| | 1882 | assert(t.length > 0); |
|---|
| | 1883 | } |
|---|
| | 1884 | } |
|---|
| | 1885 | |
|---|
| | 1886 | |
|---|
| | 1887 | /++ |
|---|
| | 1888 | Generic way of converting between two time units. Conversions to smaller |
|---|
| | 1889 | units use truncating division. |
|---|
| | 1890 | |
|---|
| | 1891 | Params: |
|---|
| | 1892 | tuFrom = The units of time to covert from. |
|---|
| | 1893 | tuFrom = The units of time to covert type. |
|---|
| | 1894 | value = The value to convert. |
|---|
| | 1895 | |
|---|
| | 1896 | Examples: |
|---|
| | 1897 | -------------------- |
|---|
| | 1898 | assert(convert!("years", "months")(1) == 12); |
|---|
| | 1899 | assert(convert!("months", "years")(12) == 1); |
|---|
| | 1900 | -------------------- |
|---|
| | 1901 | +/ |
|---|
| | 1902 | @safe |
|---|
| | 1903 | long convert(string from, string to)(long value) pure nothrow |
|---|
| | 1904 | if((from == "years" || from == "months") && |
|---|
| | 1905 | (to == "years" || to == "months")) |
|---|
| | 1906 | { |
|---|
| | 1907 | static if(from == "years") |
|---|
| | 1908 | { |
|---|
| | 1909 | static if(to == "years") |
|---|
| | 1910 | return value; |
|---|
| | 1911 | else static if(to == "months") |
|---|
| | 1912 | return value * 12; |
|---|
| 224 | | static if( op == "-" ) |
|---|
| | 1914 | static assert(0, "A generic month or year cannot be converted to or from smaller units."); |
|---|
| | 1915 | } |
|---|
| | 1916 | else static if(from == "months") |
|---|
| | 1917 | { |
|---|
| | 1918 | static if(to == "years") |
|---|
| | 1919 | return value / 12; |
|---|
| | 1920 | else static if(to == "months") |
|---|
| | 1921 | return value; |
|---|
| | 1922 | else |
|---|
| | 1923 | static assert(0, "A generic month or year cannot be converted to or from smaller units."); |
|---|
| | 1924 | } |
|---|
| | 1925 | else |
|---|
| | 1926 | static assert(0, "Template constraint broken. Invalid time unit string."); |
|---|
| | 1927 | } |
|---|
| | 1928 | |
|---|
| | 1929 | unittest |
|---|
| | 1930 | { |
|---|
| | 1931 | static assert(!__traits(compiles, convert!("years", "weeks")(12))); |
|---|
| | 1932 | static assert(!__traits(compiles, convert!("years", "days")(12))); |
|---|
| | 1933 | static assert(!__traits(compiles, convert!("years", "hours")(12))); |
|---|
| | 1934 | static assert(!__traits(compiles, convert!("years", "seconds")(12))); |
|---|
| | 1935 | static assert(!__traits(compiles, convert!("years", "msecs")(12))); |
|---|
| | 1936 | static assert(!__traits(compiles, convert!("years", "usecs")(12))); |
|---|
| | 1937 | static assert(!__traits(compiles, convert!("years", "hnsecs")(12))); |
|---|
| | 1938 | |
|---|
| | 1939 | static assert(!__traits(compiles, convert!("weeks", "years")(12))); |
|---|
| | 1940 | static assert(!__traits(compiles, convert!("days", "years")(12))); |
|---|
| | 1941 | static assert(!__traits(compiles, convert!("hours", "years")(12))); |
|---|
| | 1942 | static assert(!__traits(compiles, convert!("seconds", "years")(12))); |
|---|
| | 1943 | static assert(!__traits(compiles, convert!("msecs", "years")(12))); |
|---|
| | 1944 | static assert(!__traits(compiles, convert!("usecs", "years")(12))); |
|---|
| | 1945 | static assert(!__traits(compiles, convert!("hnsecs", "years")(12))); |
|---|
| | 1946 | |
|---|
| | 1947 | assert(convert!("years", "years")(12) == 12); |
|---|
| | 1948 | assert(convert!("months", "months")(12) == 12); |
|---|
| | 1949 | |
|---|
| | 1950 | //Verify Examples. |
|---|
| | 1951 | assert(convert!("years", "months")(1) == 12); |
|---|
| | 1952 | assert(convert!("months", "years")(12) == 1); |
|---|
| | 1953 | } |
|---|
| | 1954 | |
|---|
| | 1955 | |
|---|
| | 1956 | /++ |
|---|
| | 1957 | Generic way of converting between two time units. Conversions to smaller |
|---|
| | 1958 | units use truncating division. |
|---|
| | 1959 | |
|---|
| | 1960 | Params: |
|---|
| | 1961 | tuFrom = The units of time to covert from. |
|---|
| | 1962 | tuFrom = The units of time to covert type. |
|---|
| | 1963 | value = The value to convert. |
|---|
| | 1964 | |
|---|
| | 1965 | Examples: |
|---|
| | 1966 | -------------------- |
|---|
| | 1967 | assert(convert!("weeks", "days")(1) == 7); |
|---|
| | 1968 | assert(convert!("hours", "seconds")(1) == 3600); |
|---|
| | 1969 | assert(convert!("seconds", "days")(1) == 0); |
|---|
| | 1970 | assert(convert!("seconds", "days")(86_400) == 1); |
|---|
| | 1971 | -------------------- |
|---|
| | 1972 | +/ |
|---|
| | 1973 | @safe |
|---|
| | 1974 | static long convert(string from, string to)(long value) pure nothrow |
|---|
| | 1975 | if((from == "weeks" || |
|---|
| | 1976 | from == "days" || |
|---|
| | 1977 | from == "hours" || |
|---|
| | 1978 | from == "minutes" || |
|---|
| | 1979 | from == "seconds" || |
|---|
| | 1980 | from == "msecs" || |
|---|
| | 1981 | from == "usecs" || |
|---|
| | 1982 | from == "hnsecs") && |
|---|
| | 1983 | (to == "weeks" || |
|---|
| | 1984 | to == "days" || |
|---|
| | 1985 | to == "hours" || |
|---|
| | 1986 | to == "minutes" || |
|---|
| | 1987 | to == "seconds" || |
|---|
| | 1988 | to == "msecs" || |
|---|
| | 1989 | to == "usecs" || |
|---|
| | 1990 | to == "hnsecs")) |
|---|
| | 1991 | { |
|---|
| | 1992 | return (hnsecsPer!from * value) / hnsecsPer!to; |
|---|
| | 1993 | } |
|---|
| | 1994 | |
|---|
| | 1995 | unittest |
|---|
| | 1996 | { |
|---|
| | 1997 | assert(convert!("weeks", "hnsecs")(1) == 6_048_000_000_000L); |
|---|
| | 1998 | assert(convert!("days", "hnsecs")(1) == 864_000_000_000L); |
|---|
| | 1999 | assert(convert!("hours", "hnsecs")(1) == 36_000_000_000L); |
|---|
| | 2000 | assert(convert!("minutes", "hnsecs")(1) == 600_000_000L); |
|---|
| | 2001 | assert(convert!("seconds", "hnsecs")(1) == 10_000_000L); |
|---|
| | 2002 | assert(convert!("msecs", "hnsecs")(1) == 10_000); |
|---|
| | 2003 | assert(convert!("usecs", "hnsecs")(1) == 10); |
|---|
| | 2004 | |
|---|
| | 2005 | assert(convert!("hnsecs", "weeks")(6_048_000_000_000L) == 1); |
|---|
| | 2006 | assert(convert!("hnsecs", "days")(864_000_000_000L) == 1); |
|---|
| | 2007 | assert(convert!("hnsecs", "hours")(36_000_000_000L) == 1); |
|---|
| | 2008 | assert(convert!("hnsecs", "minutes")(600_000_000L) == 1); |
|---|
| | 2009 | assert(convert!("hnsecs", "seconds")(10_000_000L) == 1); |
|---|
| | 2010 | assert(convert!("hnsecs", "msecs")(10_000) == 1); |
|---|
| | 2011 | assert(convert!("hnsecs", "usecs")(10) == 1); |
|---|
| | 2012 | |
|---|
| | 2013 | assert(convert!("weeks", "weeks")(12) == 12); |
|---|
| | 2014 | assert(convert!("days", "days")(12) == 12); |
|---|
| | 2015 | assert(convert!("hours", "hours")(12) == 12); |
|---|
| | 2016 | assert(convert!("minutes", "minutes")(12) == 12); |
|---|
| | 2017 | assert(convert!("seconds", "seconds")(12) == 12); |
|---|
| | 2018 | assert(convert!("msecs", "msecs")(12) == 12); |
|---|
| | 2019 | assert(convert!("usecs", "usecs")(12) == 12); |
|---|
| | 2020 | assert(convert!("hnsecs", "hnsecs")(12) == 12); |
|---|
| | 2021 | |
|---|
| | 2022 | assert(convert!("weeks", "days")(1) == 7); |
|---|
| | 2023 | assert(convert!("days", "weeks")(7) == 1); |
|---|
| | 2024 | |
|---|
| | 2025 | assert(convert!("days", "hours")(1) == 24); |
|---|
| | 2026 | assert(convert!("hours", "days")(24) == 1); |
|---|
| | 2027 | |
|---|
| | 2028 | assert(convert!("hours", "minutes")(1) == 60); |
|---|
| | 2029 | assert(convert!("minutes", "hours")(60) == 1); |
|---|
| | 2030 | |
|---|
| | 2031 | assert(convert!("minutes", "seconds")(1) == 60); |
|---|
| | 2032 | assert(convert!("seconds", "minutes")(60) == 1); |
|---|
| | 2033 | |
|---|
| | 2034 | assert(convert!("seconds", "msecs")(1) == 1000); |
|---|
| | 2035 | assert(convert!("msecs", "seconds")(1000) == 1); |
|---|
| | 2036 | |
|---|
| | 2037 | assert(convert!("msecs", "usecs")(1) == 1000); |
|---|
| | 2038 | assert(convert!("usecs", "msecs")(1000) == 1); |
|---|
| | 2039 | |
|---|
| | 2040 | assert(convert!("usecs", "hnsecs")(1) == 10); |
|---|
| | 2041 | assert(convert!("hnsecs", "usecs")(10) == 1); |
|---|
| | 2042 | |
|---|
| | 2043 | assert(convert!("hnsecs", "hnsecs")(10) == 10); |
|---|
| | 2044 | assert(convert!("hnsecs", "hnsecs")(10) == 10); |
|---|
| | 2045 | |
|---|
| | 2046 | //Verify Examples. |
|---|
| | 2047 | assert(convert!("weeks", "days")(1) == 7); |
|---|
| | 2048 | assert(convert!("hours", "seconds")(1) == 3600); |
|---|
| | 2049 | assert(convert!("seconds", "days")(1) == 0); |
|---|
| | 2050 | assert(convert!("seconds", "days")(86_400) == 1); |
|---|
| | 2051 | } |
|---|
| | 2052 | |
|---|
| | 2053 | |
|---|
| | 2054 | /++ |
|---|
| | 2055 | Generic way of converting between two time units. Conversions to smaller |
|---|
| | 2056 | units use truncating division. |
|---|
| | 2057 | |
|---|
| | 2058 | Params: |
|---|
| | 2059 | tuFrom = The units of time to covert from. |
|---|
| | 2060 | tuFrom = The units of time to covert type. |
|---|
| | 2061 | value = The value to convert. |
|---|
| | 2062 | |
|---|
| | 2063 | Examples: |
|---|
| | 2064 | -------------------- |
|---|
| | 2065 | assert(convert!("nsecs", "nsecs")(1) == 1); |
|---|
| | 2066 | assert(convert!("nsecs", "hnsecs")(1) == 0); |
|---|
| | 2067 | assert(convert!("hnsecs", "nsecs")(1) == 100); |
|---|
| | 2068 | assert(convert!("nsecs", "seconds")(1) == 0); |
|---|
| | 2069 | assert(convert!("seconds", "nsecs")(1) == 1_000_000_000); |
|---|
| | 2070 | -------------------- |
|---|
| | 2071 | +/ |
|---|
| | 2072 | @safe |
|---|
| | 2073 | static long convert(string from, string to)(long value) pure nothrow |
|---|
| | 2074 | if((from == "nsecs" && |
|---|
| | 2075 | (to == "weeks" || |
|---|
| | 2076 | to == "days" || |
|---|
| | 2077 | to == "hours" || |
|---|
| | 2078 | to == "minutes" || |
|---|
| | 2079 | to == "seconds" || |
|---|
| | 2080 | to == "msecs" || |
|---|
| | 2081 | to == "usecs" || |
|---|
| | 2082 | to == "hnsecs" || |
|---|
| | 2083 | to == "nsecs")) || |
|---|
| | 2084 | (to == "nsecs" && |
|---|
| | 2085 | (from == "weeks" || |
|---|
| | 2086 | from == "days" || |
|---|
| | 2087 | from == "hours" || |
|---|
| | 2088 | from == "minutes" || |
|---|
| | 2089 | from == "seconds" || |
|---|
| | 2090 | from == "msecs" || |
|---|
| | 2091 | from == "usecs" || |
|---|
| | 2092 | from == "hnsecs" || |
|---|
| | 2093 | from == "nsecs"))) |
|---|
| | 2094 | { |
|---|
| | 2095 | static if(from == "nsecs" && to == "nsecs") |
|---|
| | 2096 | return value; |
|---|
| | 2097 | else static if(from == "nsecs") |
|---|
| | 2098 | return convert!("hnsecs", to)(value / 100); |
|---|
| | 2099 | else static if(to == "nsecs") |
|---|
| | 2100 | return convert!(from, "hnsecs")(value) * 100; |
|---|
| | 2101 | else |
|---|
| | 2102 | static assert(0); |
|---|
| | 2103 | } |
|---|
| | 2104 | |
|---|
| | 2105 | unittest |
|---|
| | 2106 | { |
|---|
| | 2107 | assert(convert!("weeks", "nsecs")(1) == 604_800_000_000_000L); |
|---|
| | 2108 | assert(convert!("days", "nsecs")(1) == 86_400_000_000_000L); |
|---|
| | 2109 | assert(convert!("hours", "nsecs")(1) == 3_600_000_000_000L); |
|---|
| | 2110 | assert(convert!("minutes", "nsecs")(1) == 60_000_000_000L); |
|---|
| | 2111 | assert(convert!("seconds", "nsecs")(1) == 1_000_000_000L); |
|---|
| | 2112 | assert(convert!("msecs", "nsecs")(1) == 1_000_000); |
|---|
| | 2113 | assert(convert!("usecs", "nsecs")(1) == 1000); |
|---|
| | 2114 | assert(convert!("hnsecs", "nsecs")(1) == 100); |
|---|
| | 2115 | |
|---|
| | 2116 | assert(convert!("nsecs", "weeks")(604_800_000_000_000L) == 1); |
|---|
| | 2117 | assert(convert!("nsecs", "days")(86_400_000_000_000L) == 1); |
|---|
| | 2118 | assert(convert!("nsecs", "hours")(3_600_000_000_000L) == 1); |
|---|
| | 2119 | assert(convert!("nsecs", "minutes")(60_000_000_000L) == 1); |
|---|
| | 2120 | assert(convert!("nsecs", "seconds")(1_000_000_000L) == 1); |
|---|
| | 2121 | assert(convert!("nsecs", "msecs")(1_000_000) == 1); |
|---|
| | 2122 | assert(convert!("nsecs", "usecs")(1000) == 1); |
|---|
| | 2123 | assert(convert!("nsecs", "hnsecs")(100) == 1); |
|---|
| | 2124 | |
|---|
| | 2125 | assert(convert!("nsecs", "nsecs")(1) == 1); |
|---|
| | 2126 | |
|---|
| | 2127 | //Verify Examples. |
|---|
| | 2128 | assert(convert!("nsecs", "nsecs")(1) == 1); |
|---|
| | 2129 | assert(convert!("nsecs", "hnsecs")(1) == 0); |
|---|
| | 2130 | assert(convert!("hnsecs", "nsecs")(1) == 100); |
|---|
| | 2131 | assert(convert!("nsecs", "seconds")(1) == 0); |
|---|
| | 2132 | assert(convert!("seconds", "nsecs")(1) == 1_000_000_000); |
|---|
| | 2133 | } |
|---|
| | 2134 | |
|---|
| | 2135 | |
|---|
| | 2136 | /++ |
|---|
| | 2137 | Represents fractional seconds. |
|---|
| | 2138 | |
|---|
| | 2139 | This is the portion of the time which is smaller than a second and cannot |
|---|
| | 2140 | hold values which would equal or exceed a second. |
|---|
| | 2141 | |
|---|
| | 2142 | It holds hnsecs internally, but you can create it using either milliseconds, |
|---|
| | 2143 | microseconds, or hnsecs. What it does is allow for a simple way to set or adjust |
|---|
| | 2144 | the fractional seconds portion of a Duration or a std.datetime.SysTime without |
|---|
| | 2145 | having to worry about whether you're dealing with milliseconds, microseconds, |
|---|
| | 2146 | or hnsecs. |
|---|
| | 2147 | |
|---|
| | 2148 | FracSec's functions which take time unit strings do accept "nsecs", but the |
|---|
| | 2149 | because the resolution for Duration and std.datetime.SysTime is hnsecs, you |
|---|
| | 2150 | don't actually get precision higher than hnsecs. "nsecs" is accepted merely |
|---|
| | 2151 | for convenience. Any values given as nsecs will be converted to hnsecs using |
|---|
| | 2152 | convert!() (which uses truncation when converting to smaller units). |
|---|
| | 2153 | +/ |
|---|
| | 2154 | struct FracSec |
|---|
| | 2155 | { |
|---|
| | 2156 | public: |
|---|
| | 2157 | |
|---|
| | 2158 | /++ |
|---|
| | 2159 | Create a FracSec from the given units ("msecs", "usecs", or "hnsecs"). |
|---|
| | 2160 | |
|---|
| | 2161 | Params: |
|---|
| | 2162 | units = The units to create a FracSec from. |
|---|
| | 2163 | value = The number of the given units passed the second. |
|---|
| | 2164 | |
|---|
| | 2165 | Throws: |
|---|
| | 2166 | TimeException if the given value is less than 0 or would result in a |
|---|
| | 2167 | FracSec greater than or equal to 1 second. |
|---|
| | 2168 | +/ |
|---|
| | 2169 | static FracSec from(string units)(int value) pure |
|---|
| | 2170 | if(units == "msecs" || |
|---|
| | 2171 | units == "usecs" || |
|---|
| | 2172 | units == "hnsecs" || |
|---|
| | 2173 | units == "nsecs") |
|---|
| | 2174 | { |
|---|
| | 2175 | return FracSec(cast(int)convert!(units, "hnsecs")(value)); |
|---|
| | 2176 | } |
|---|
| | 2177 | |
|---|
| | 2178 | unittest |
|---|
| | 2179 | { |
|---|
| | 2180 | tAssertExThrown!TimeException(from!"msecs"(-1)); |
|---|
| | 2181 | tAssertExThrown!TimeException(from!"msecs"(1000)); |
|---|
| | 2182 | |
|---|
| | 2183 | assert(FracSec.from!"msecs"(0) == FracSec(0)); |
|---|
| | 2184 | assert(FracSec.from!"msecs"(1) == FracSec(10_000)); |
|---|
| | 2185 | assert(FracSec.from!"msecs"(999) == FracSec(9_990_000)); |
|---|
| | 2186 | |
|---|
| | 2187 | tAssertExThrown!TimeException(from!"usecs"(-1)); |
|---|
| | 2188 | tAssertExThrown!TimeException(from!"usecs"(1_000_000)); |
|---|
| | 2189 | |
|---|
| | 2190 | assert(FracSec.from!"usecs"(0) == FracSec(0)); |
|---|
| | 2191 | assert(FracSec.from!"usecs"(1) == FracSec(10)); |
|---|
| | 2192 | assert(FracSec.from!"usecs"(999) == FracSec(9990)); |
|---|
| | 2193 | assert(FracSec.from!"usecs"(999_999) == FracSec(9999_990)); |
|---|
| | 2194 | |
|---|
| | 2195 | tAssertExThrown!TimeException(from!"hnsecs"(-1)); |
|---|
| | 2196 | tAssertExThrown!TimeException(from!"hnsecs"(10_000_000)); |
|---|
| | 2197 | |
|---|
| | 2198 | assert(FracSec.from!"hnsecs"(0) == FracSec(0)); |
|---|
| | 2199 | assert(FracSec.from!"hnsecs"(1) == FracSec(1)); |
|---|
| | 2200 | assert(FracSec.from!"hnsecs"(999) == FracSec(999)); |
|---|
| | 2201 | assert(FracSec.from!"hnsecs"(999_999) == FracSec(999_999)); |
|---|
| | 2202 | assert(FracSec.from!"hnsecs"(9_999_999) == FracSec(9_999_999)); |
|---|
| | 2203 | |
|---|
| | 2204 | assert(FracSec.from!"nsecs"(0) == FracSec(0)); |
|---|
| | 2205 | assert(FracSec.from!"nsecs"(1) == FracSec(0)); |
|---|
| | 2206 | assert(FracSec.from!"nsecs"(10) == FracSec(0)); |
|---|
| | 2207 | assert(FracSec.from!"nsecs"(99) == FracSec(0)); |
|---|
| | 2208 | assert(FracSec.from!"nsecs"(100) == FracSec(1)); |
|---|
| | 2209 | assert(FracSec.from!"nsecs"(99_999) == FracSec(999)); |
|---|
| | 2210 | assert(FracSec.from!"nsecs"(99_999_999) == FracSec(999_999)); |
|---|
| | 2211 | assert(FracSec.from!"nsecs"(999_999_999) == FracSec(9_999_999)); |
|---|
| | 2212 | } |
|---|
| | 2213 | |
|---|
| | 2214 | |
|---|
| | 2215 | /++ |
|---|
| | 2216 | The value of this FracSec as milliseconds. |
|---|
| | 2217 | +/ |
|---|
| | 2218 | @property int msecs() const pure nothrow |
|---|
| | 2219 | { |
|---|
| | 2220 | return cast(int)convert!("hnsecs", "msecs")(_hnsecs); |
|---|
| | 2221 | } |
|---|
| | 2222 | |
|---|
| | 2223 | unittest |
|---|
| | 2224 | { |
|---|
| | 2225 | assert(FracSec(0).msecs == 0); |
|---|
| | 2226 | assert(FracSec(1).msecs == 0); |
|---|
| | 2227 | assert(FracSec(999).msecs == 0); |
|---|
| | 2228 | assert(FracSec(999_999).msecs == 99); |
|---|
| | 2229 | assert(FracSec(9_999_999).msecs == 999); |
|---|
| | 2230 | |
|---|
| | 2231 | auto fs = FracSec(12); |
|---|
| | 2232 | const cfs = FracSec(12); |
|---|
| | 2233 | immutable ifs = FracSec(12); |
|---|
| | 2234 | static assert(__traits(compiles, fs.msecs)); |
|---|
| | 2235 | static assert(__traits(compiles, cfs.msecs)); |
|---|
| | 2236 | static assert(__traits(compiles, ifs.msecs)); |
|---|
| | 2237 | } |
|---|
| | 2238 | |
|---|
| | 2239 | |
|---|
| | 2240 | /++ |
|---|
| | 2241 | The value of this FracSec as milliseconds. |
|---|
| | 2242 | |
|---|
| | 2243 | Params: |
|---|
| | 2244 | milliseconds = The number of milliseconds passed the second. |
|---|
| | 2245 | |
|---|
| | 2246 | Throws: |
|---|
| | 2247 | TimeException if the given value is not less than one second. |
|---|
| | 2248 | +/ |
|---|
| | 2249 | @property void msecs(int milliseconds) pure |
|---|
| | 2250 | { |
|---|
| | 2251 | immutable hnsecs = cast(int)convert!("msecs", "hnsecs")(milliseconds); |
|---|
| | 2252 | |
|---|
| | 2253 | _enforceValid(hnsecs); |
|---|
| | 2254 | _hnsecs = hnsecs; |
|---|
| | 2255 | } |
|---|
| | 2256 | |
|---|
| | 2257 | unittest |
|---|
| | 2258 | { |
|---|
| | 2259 | static void testFS(int ms, in FracSec expected = FracSec.init, size_t line = __LINE__) |
|---|
| | 2268 | |
|---|
| | 2269 | tAssertExThrown!TimeException(testFS(-1)); |
|---|
| | 2270 | tAssertExThrown!TimeException(testFS(1000)); |
|---|
| | 2271 | |
|---|
| | 2272 | testFS(0, FracSec(0)); |
|---|
| | 2273 | testFS(1, FracSec(10_000)); |
|---|
| | 2274 | testFS(999, FracSec(9_990_000)); |
|---|
| | 2275 | |
|---|
| | 2276 | auto fs = FracSec(12); |
|---|
| | 2277 | const cfs = FracSec(12); |
|---|
| | 2278 | immutable ifs = FracSec(12); |
|---|
| | 2279 | static assert(__traits(compiles, fs.msecs = 54)); |
|---|
| | 2280 | static assert(!__traits(compiles, cfs.msecs = 54)); |
|---|
| | 2281 | static assert(!__traits(compiles, ifs.msecs = 54)); |
|---|
| | 2282 | } |
|---|
| | 2283 | |
|---|
| | 2284 | |
|---|
| | 2285 | /++ |
|---|
| | 2286 | The value of this FracSec as microseconds. |
|---|
| | 2287 | +/ |
|---|
| | 2288 | @property int usecs() const pure nothrow |
|---|
| | 2289 | { |
|---|
| | 2290 | return cast(int)convert!("hnsecs", "usecs")(_hnsecs); |
|---|
| | 2291 | } |
|---|
| | 2292 | |
|---|
| | 2293 | unittest |
|---|
| | 2294 | { |
|---|
| | 2295 | assert(FracSec(0).usecs == 0); |
|---|
| | 2296 | assert(FracSec(1).usecs == 0); |
|---|
| | 2297 | assert(FracSec(999).usecs == 99); |
|---|
| | 2298 | assert(FracSec(999_999).usecs == 99_999); |
|---|
| | 2299 | assert(FracSec(9_999_999).usecs == 999_999); |
|---|
| | 2300 | |
|---|
| | 2301 | auto fs = FracSec(12); |
|---|
| | 2302 | const cfs = FracSec(12); |
|---|
| | 2303 | immutable ifs = FracSec(12); |
|---|
| | 2304 | static assert(__traits(compiles, fs.usecs)); |
|---|
| | 2305 | static assert(__traits(compiles, cfs.usecs)); |
|---|
| | 2306 | static assert(__traits(compiles, ifs.usecs)); |
|---|
| | 2307 | } |
|---|
| | 2308 | |
|---|
| | 2309 | |
|---|
| | 2310 | /++ |
|---|
| | 2311 | The value of this FracSec as microseconds. |
|---|
| | 2312 | |
|---|
| | 2313 | Params: |
|---|
| | 2314 | microseconds = The number of microseconds passed the second. |
|---|
| | 2315 | |
|---|
| | 2316 | Throws: |
|---|
| | 2317 | TimeException if the given value is not less than one second. |
|---|
| | 2318 | +/ |
|---|
| | 2319 | @property void usecs(int microseconds) pure |
|---|
| | 2320 | { |
|---|
| | 2321 | immutable hnsecs = cast(int)convert!("usecs", "hnsecs")(microseconds); |
|---|
| | 2322 | |
|---|
| | 2323 | _enforceValid(hnsecs); |
|---|
| | 2324 | _hnsecs = hnsecs; |
|---|
| | 2325 | } |
|---|
| | 2326 | |
|---|
| | 2327 | unittest |
|---|
| | 2328 | { |
|---|
| | 2329 | static void testFS(int ms, in FracSec expected = FracSec.init, size_t line = __LINE__) |
|---|
| | 2330 | { |
|---|
| | 2331 | FracSec fs; |
|---|
| | 2332 | |
|---|
| | 2333 | fs.usecs = ms; |
|---|
| | 2334 | |
|---|
| | 2335 | if(fs != expected) |
|---|
| | 2336 | throw new AssertError("", __FILE__, line); |
|---|
| | 2337 | } |
|---|
| | 2338 | |
|---|
| | 2339 | tAssertExThrown!TimeException(testFS(-1)); |
|---|
| | 2340 | tAssertExThrown!TimeException(testFS(1_000_000)); |
|---|
| | 2341 | |
|---|
| | 2342 | testFS(0, FracSec(0)); |
|---|
| | 2343 | testFS(1, FracSec(10)); |
|---|
| | 2344 | testFS(999, FracSec(9990)); |
|---|
| | 2345 | testFS(999_999, FracSec(9_999_990)); |
|---|
| | 2346 | |
|---|
| | 2347 | auto fs = FracSec(12); |
|---|
| | 2348 | const cfs = FracSec(12); |
|---|
| | 2349 | immutable ifs = FracSec(12); |
|---|
| | 2350 | static assert(__traits(compiles, fs.usecs = 54)); |
|---|
| | 2351 | static assert(!__traits(compiles, cfs.usecs = 54)); |
|---|
| | 2352 | static assert(!__traits(compiles, ifs.usecs = 54)); |
|---|
| | 2353 | } |
|---|
| | 2354 | |
|---|
| | 2355 | |
|---|
| | 2356 | /++ |
|---|
| | 2357 | The value of this FracSec as hnsecs. |
|---|
| | 2358 | +/ |
|---|
| | 2359 | @property int hnsecs() const pure nothrow |
|---|
| | 2360 | { |
|---|
| | 2361 | return _hnsecs; |
|---|
| | 2362 | } |
|---|
| | 2363 | |
|---|
| | 2364 | unittest |
|---|
| | 2365 | { |
|---|
| | 2366 | assert(FracSec(0).hnsecs == 0); |
|---|
| | 2367 | assert(FracSec(1).hnsecs == 1); |
|---|
| | 2368 | assert(FracSec(999).hnsecs == 999); |
|---|
| | 2369 | assert(FracSec(999_999).hnsecs == 999_999); |
|---|
| | 2370 | assert(FracSec(9_999_999).hnsecs == 9_999_999); |
|---|
| | 2371 | |
|---|
| | 2372 | auto fs = FracSec(12); |
|---|
| | 2373 | const cfs = FracSec(12); |
|---|
| | 2374 | immutable ifs = FracSec(12); |
|---|
| | 2375 | static assert(__traits(compiles, fs.hnsecs)); |
|---|
| | 2376 | static assert(__traits(compiles, cfs.hnsecs)); |
|---|
| | 2377 | static assert(__traits(compiles, ifs.hnsecs)); |
|---|
| | 2378 | } |
|---|
| | 2379 | |
|---|
| | 2380 | |
|---|
| | 2381 | /++ |
|---|
| | 2382 | The value of this FracSec as hnsecs. |
|---|
| | 2383 | |
|---|
| | 2384 | Params: |
|---|
| | 2385 | hnsecs = The number of hnsecs passed the second. |
|---|
| | 2386 | |
|---|
| | 2387 | Throws: |
|---|
| | 2388 | TimeException if the given value is not less than one second. |
|---|
| | 2389 | +/ |
|---|
| | 2390 | @property void hnsecs(int hnsecs) pure |
|---|
| | 2391 | { |
|---|
| | 2392 | _enforceValid(hnsecs); |
|---|
| | 2393 | _hnsecs = hnsecs; |
|---|
| | 2394 | } |
|---|
| | 2395 | |
|---|
| | 2396 | unittest |
|---|
| | 2397 | { |
|---|
| | 2398 | static void testFS(int hnsecs, in FracSec expected = FracSec.init, size_t line = __LINE__) |
|---|
| | 2399 | { |
|---|
| | 2400 | FracSec fs; |
|---|
| | 2401 | |
|---|
| | 2402 | fs.hnsecs = hnsecs; |
|---|
| | 2403 | |
|---|
| | 2404 | if(fs != expected) |
|---|
| | 2405 | throw new AssertError("", __FILE__, line); |
|---|
| | 2406 | } |
|---|
| | 2407 | |
|---|
| | 2408 | tAssertExThrown!TimeException(testFS(-1)); |
|---|
| | 2409 | tAssertExThrown!TimeException(testFS(10_000_000)); |
|---|
| | 2410 | |
|---|
| | 2411 | testFS(0, FracSec(0)); |
|---|
| | 2412 | testFS(1, FracSec(1)); |
|---|
| | 2413 | testFS(999, FracSec(999)); |
|---|
| | 2414 | testFS(999_999, FracSec(999_999)); |
|---|
| | 2415 | testFS(9_999_999, FracSec(9_999_999)); |
|---|
| | 2416 | |
|---|
| | 2417 | auto fs = FracSec(12); |
|---|
| | 2418 | const cfs = FracSec(12); |
|---|
| | 2419 | immutable ifs = FracSec(12); |
|---|
| | 2420 | static assert(__traits(compiles, fs.hnsecs = 54)); |
|---|
| | 2421 | static assert(!__traits(compiles, cfs.hnsecs = 54)); |
|---|
| | 2422 | static assert(!__traits(compiles, ifs.hnsecs = 54)); |
|---|
| | 2423 | } |
|---|
| | 2424 | |
|---|
| | 2425 | |
|---|
| | 2426 | /++ |
|---|
| | 2427 | The value of this FracSec as nsecs. |
|---|
| | 2428 | |
|---|
| | 2429 | Note that this does not give you any greater precision |
|---|
| | 2430 | than getting the value of this FracSec as hnsecs. |
|---|
| | 2431 | +/ |
|---|
| | 2432 | @property int nsecs() const pure nothrow |
|---|
| | 2433 | { |
|---|
| | 2434 | return cast(int)convert!("hnsecs", "nsecs")(_hnsecs); |
|---|
| | 2435 | } |
|---|
| | 2436 | |
|---|
| | 2437 | unittest |
|---|
| | 2438 | { |
|---|
| | 2439 | assert(FracSec(0).nsecs == 0); |
|---|
| | 2440 | assert(FracSec(1).nsecs == 100); |
|---|
| | 2441 | assert(FracSec(999).nsecs == 99_900); |
|---|
| | 2442 | assert(FracSec(999_999).nsecs == 99_999_900); |
|---|
| | 2443 | assert(FracSec(9_999_999).nsecs == 999_999_900); |
|---|
| | 2444 | |
|---|
| | 2445 | auto fs = FracSec(12); |
|---|
| | 2446 | const cfs = FracSec(12); |
|---|
| | 2447 | immutable ifs = FracSec(12); |
|---|
| | 2448 | static assert(__traits(compiles, fs.nsecs)); |
|---|
| | 2449 | static assert(__traits(compiles, cfs.nsecs)); |
|---|
| | 2450 | static assert(__traits(compiles, ifs.nsecs)); |
|---|
| | 2451 | } |
|---|
| | 2452 | |
|---|
| | 2453 | |
|---|
| | 2454 | /++ |
|---|
| | 2455 | The value of this FracSec as nsecs. |
|---|
| | 2456 | |
|---|
| | 2457 | Note that this does not give you any greater precision |
|---|
| | 2458 | than setting the value of this FracSec as hnsecs. |
|---|
| | 2459 | |
|---|
| | 2460 | Params: |
|---|
| | 2461 | nsecs = The number of nsecs passed the second. |
|---|
| | 2462 | |
|---|
| | 2463 | Throws: |
|---|
| | 2464 | TimeException if the given value is not less than one second. |
|---|
| | 2465 | +/ |
|---|
| | 2466 | @property void nsecs(int nsecs) pure |
|---|
| | 2467 | { |
|---|
| | 2468 | //So that -99 through -1 throw instead of result in FracSec(0). |
|---|
| | 2469 | if(nsecs < 0) |
|---|
| | 2470 | _enforceValid(-1); |
|---|
| | 2471 | |
|---|
| | 2472 | immutable hnsecs = cast(int)convert!("nsecs", "hnsecs")(nsecs); |
|---|
| | 2473 | |
|---|
| | 2474 | _enforceValid(hnsecs); |
|---|
| | 2475 | _hnsecs = hnsecs; |
|---|
| | 2476 | } |
|---|
| | 2477 | |
|---|
| | 2478 | unittest |
|---|
| | 2479 | { |
|---|
| | 2480 | static void testFS(int nsecs, in FracSec expected = FracSec.init, size_t line = __LINE__) |
|---|
| | 2481 | { |
|---|
| | 2482 | FracSec fs; |
|---|
| | 2483 | |
|---|
| | 2484 | fs.nsecs = nsecs; |
|---|
| | 2485 | |
|---|
| | 2486 | if(fs != expected) |
|---|
| | 2487 | throw new AssertError("", __FILE__, line); |
|---|
| | 2488 | } |
|---|
| | 2489 | |
|---|
| | 2490 | tAssertExThrown!TimeException(testFS(-1)); |
|---|
| | 2491 | tAssertExThrown!TimeException(testFS(1_000_000_000)); |
|---|
| | 2492 | |
|---|
| | 2493 | testFS(0, FracSec(0)); |
|---|
| | 2494 | testFS(1, FracSec(0)); |
|---|
| | 2495 | testFS(10, FracSec(0)); |
|---|
| | 2496 | testFS(100, FracSec(1)); |
|---|
| | 2497 | testFS(999, FracSec(9)); |
|---|
| | 2498 | testFS(999_999, FracSec(9999)); |
|---|
| | 2499 | testFS(9_999_999, FracSec(99_999)); |
|---|
| | 2500 | |
|---|
| | 2501 | auto fs = FracSec(12); |
|---|
| | 2502 | const cfs = FracSec(12); |
|---|
| | 2503 | immutable ifs = FracSec(12); |
|---|
| | 2504 | static assert(__traits(compiles, fs.nsecs = 54)); |
|---|
| | 2505 | static assert(!__traits(compiles, cfs.nsecs = 54)); |
|---|
| | 2506 | static assert(!__traits(compiles, ifs.nsecs = 54)); |
|---|
| | 2507 | } |
|---|
| | 2508 | |
|---|
| | 2509 | |
|---|
| | 2510 | /+ |
|---|
| | 2511 | Converts this duration to a string. |
|---|
| | 2512 | +/ |
|---|
| | 2513 | //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't |
|---|
| | 2514 | //have versions of toString() with extra modifiers, so we define one version |
|---|
| | 2515 | //with modifiers and one without. |
|---|
| | 2516 | string toString() |
|---|
| | 2517 | { |
|---|
| | 2518 | return _toStringImpl(); |
|---|
| | 2519 | } |
|---|
| | 2520 | |
|---|
| | 2521 | |
|---|
| | 2522 | /++ |
|---|
| | 2523 | Converts this duration to a string. |
|---|
| | 2524 | +/ |
|---|
| | 2525 | //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't |
|---|
| | 2526 | //have versions of toString() with extra modifiers, so we define one version |
|---|
| | 2527 | //with modifiers and one without. |
|---|
| | 2528 | string toString() const pure nothrow |
|---|
| | 2529 | { |
|---|
| | 2530 | return _toStringImpl(); |
|---|
| | 2531 | } |
|---|
| | 2532 | |
|---|
| | 2533 | unittest |
|---|
| | 2534 | { |
|---|
| | 2535 | auto fs = FracSec(12); |
|---|
| | 2536 | const cfs = FracSec(12); |
|---|
| | 2537 | immutable ifs = FracSec(12); |
|---|
| | 2538 | static assert(__traits(compiles, fs.toString())); |
|---|
| | 2539 | static assert(__traits(compiles, cfs.toString())); |
|---|
| | 2540 | static assert(__traits(compiles, ifs.toString())); |
|---|
| | 2541 | } |
|---|
| | 2542 | |
|---|
| | 2543 | |
|---|
| | 2544 | private: |
|---|
| | 2545 | |
|---|
| | 2546 | /++ |
|---|
| | 2547 | Since we have two versions of toString(), we have _toStringImpl() |
|---|
| | 2548 | so that they can share implementations. |
|---|
| | 2549 | +/ |
|---|
| | 2550 | string _toStringImpl() const pure nothrow |
|---|
| | 2551 | { |
|---|
| | 2552 | try |
|---|
| | 2553 | { |
|---|
| | 2554 | long hnsecs = _hnsecs; |
|---|
| | 2555 | |
|---|
| | 2556 | immutable milliseconds = splitUnitsFromHNSecs!"msecs"(hnsecs); |
|---|
| | 2557 | immutable microseconds = splitUnitsFromHNSecs!"usecs"(hnsecs); |
|---|
| | 2558 | |
|---|
| | 2559 | if(hnsecs == 0) |
|---|
| | 2560 | { |
|---|
| | 2561 | if(microseconds == 0) |
|---|
| | 2562 | { |
|---|
| | 2563 | if(milliseconds == 0) |
|---|
| | 2564 | return "0 hnsecs"; |
|---|
| | 2565 | else |
|---|
| | 2566 | { |
|---|
| | 2567 | if(milliseconds == 1) |
|---|
| | 2568 | return "1 ms"; |
|---|
| | 2569 | else |
|---|
| | 2570 | return numToString(milliseconds) ~ " ms"; |
|---|
| | 2571 | } |
|---|
| | 2572 | } |
|---|
| | 2573 | else |
|---|
| | 2574 | { |
|---|
| | 2575 | immutable fullMicroseconds = getUnitsFromHNSecs!"usecs"(_hnsecs); |
|---|
| | 2576 | |
|---|
| | 2577 | if(fullMicroseconds == 1) |
|---|
| | 2578 | return "1 ÃŽÅ’s"; |
|---|
| | 2579 | else |
|---|
| | 2580 | return numToString(fullMicroseconds) ~ " ÃŽÅ’s"; |
|---|
| | 2581 | } |
|---|
| | 2582 | } |
|---|
| | 2583 | else |
|---|
| | 2584 | { |
|---|
| | 2585 | if(_hnsecs == 1) |
|---|
| | 2586 | return "1 hnsec"; |
|---|
| | 2587 | else |
|---|
| | 2588 | return numToString(_hnsecs) ~ " hnsecs"; |
|---|
| | 2589 | } |
|---|
| | 2590 | } |
|---|
| | 2591 | catch(Exception e) |
|---|
| | 2592 | assert(0, "Something threw when nothing can throw."); |
|---|
| | 2593 | } |
|---|
| | 2594 | |
|---|
| | 2595 | unittest |
|---|
| | 2596 | { |
|---|
| | 2597 | assert(FracSec.from!"msecs"(0).toString() == "0 hnsecs"); |
|---|
| | 2598 | assert(FracSec.from!"msecs"(1).toString() == "1 ms"); |
|---|
| | 2599 | assert(FracSec.from!"msecs"(2).toString() == "2 ms"); |
|---|
| | 2600 | assert(FracSec.from!"msecs"(100).toString() == "100 ms"); |
|---|
| | 2601 | assert(FracSec.from!"msecs"(999).toString() == "999 ms"); |
|---|
| | 2602 | |
|---|
| | 2603 | assert(FracSec.from!"usecs"(0).toString() == "0 hnsecs"); |
|---|
| | 2604 | assert(FracSec.from!"usecs"(1).toString() == "1 ÃŽÅ’s"); |
|---|
| | 2605 | assert(FracSec.from!"usecs"(2).toString() == "2 ÃŽÅ’s"); |
|---|
| | 2606 | assert(FracSec.from!"usecs"(100).toString() == "100 ÃŽÅ’s"); |
|---|
| | 2607 | assert(FracSec.from!"usecs"(999).toString() == "999 ÃŽÅ’s"); |
|---|
| | 2608 | assert(FracSec.from!"usecs"(1000).toString() == "1 ms"); |
|---|
| | 2609 | assert(FracSec.from!"usecs"(2000).toString() == "2 ms"); |
|---|
| | 2610 | assert(FracSec.from!"usecs"(9999).toString() == "9999 ÃŽÅ’s"); |
|---|
| | 2611 | assert(FracSec.from!"usecs"(10_000).toString() == "10 ms"); |
|---|
| | 2612 | assert(FracSec.from!"usecs"(20_000).toString() == "20 ms"); |
|---|
| | 2613 | assert(FracSec.from!"usecs"(100_000).toString() == "100 ms"); |
|---|
| | 2614 | assert(FracSec.from!"usecs"(100_001).toString() == "100001 ÃŽÅ’s"); |
|---|
| | 2615 | assert(FracSec.from!"usecs"(999_999).toString() == "999999 ÃŽÅ’s"); |
|---|
| | 2616 | |
|---|
| | 2617 | assert(FracSec.from!"hnsecs"(0).toString() == "0 hnsecs"); |
|---|
| | 2618 | assert(FracSec.from!"hnsecs"(1).toString() == "1 hnsec"); |
|---|
| | 2619 | assert(FracSec.from!"hnsecs"(2).toString() == "2 hnsecs"); |
|---|
| | 2620 | assert(FracSec.from!"hnsecs"(100).toString() == "10 ÃŽÅ’s"); |
|---|
| | 2621 | assert(FracSec.from!"hnsecs"(999).toString() == "999 hnsecs"); |
|---|
| | 2622 | assert(FracSec.from!"hnsecs"(1000).toString() == "100 ÃŽÅ’s"); |
|---|
| | 2623 | assert(FracSec.from!"hnsecs"(2000).toString() == "200 ÃŽÅ’s"); |
|---|
| | 2624 | assert(FracSec.from!"hnsecs"(9999).toString() == "9999 hnsecs"); |
|---|
| | 2625 | assert(FracSec.from!"hnsecs"(10_000).toString() == "1 ms"); |
|---|
| | 2626 | assert(FracSec.from!"hnsecs"(20_000).toString() == "2 ms"); |
|---|
| | 2627 | assert(FracSec.from!"hnsecs"(100_000).toString() == "10 ms"); |
|---|
| | 2628 | assert(FracSec.from!"hnsecs"(100_001).toString() == "100001 hnsecs"); |
|---|
| | 2629 | assert(FracSec.from!"hnsecs"(200_000).toString() == "20 ms"); |
|---|
| | 2630 | assert(FracSec.from!"hnsecs"(999_999).toString() == "999999 hnsecs"); |
|---|
| | 2631 | assert(FracSec.from!"hnsecs"(1_000_001).toString() == "1000001 hnsecs"); |
|---|
| | 2632 | assert(FracSec.from!"hnsecs"(9_999_999).toString() == "9999999 hnsecs"); |
|---|
| | 2633 | } |
|---|
| | 2634 | |
|---|
| | 2635 | |
|---|
| | 2636 | /++ |
|---|
| | 2637 | Returns whether the given number of hnsecs fits within the range of FracSec. |
|---|
| | 2638 | |
|---|
| | 2639 | Params: |
|---|
| | 2640 | hnsecs = The number of hnsecs. |
|---|
| | 2641 | +/ |
|---|
| | 2642 | static bool _valid(int hnsecs) pure |
|---|
| | 2643 | { |
|---|
| | 2644 | return hnsecs >= 0 && hnsecs < convert!("seconds", "hnsecs")(1); |
|---|
| | 2645 | } |
|---|
| | 2646 | |
|---|
| | 2647 | |
|---|
| | 2648 | /++ |
|---|
| | 2649 | Throws: |
|---|
| | 2650 | TimeException if valid(hnsecs) is false. |
|---|
| | 2651 | +/ |
|---|
| | 2652 | static void _enforceValid(int hnsecs) pure |
|---|
| | 2653 | { |
|---|
| | 2654 | if(!_valid(hnsecs)) |
|---|
| | 2655 | throw new TimeException("FracSec must be greater than equal to 0 and less than 1 second."); |
|---|
| | 2656 | } |
|---|
| | 2657 | |
|---|
| | 2658 | |
|---|
| | 2659 | /++ |
|---|
| | 2660 | Params: |
|---|
| | 2661 | hnsecs = The number of hnsecs passed the second. |
|---|
| | 2662 | |
|---|
| | 2663 | Throws: |
|---|
| | 2664 | TimeException if the given hnsecs less than 0 or would result in a |
|---|
| | 2665 | FracSec greater than or equal to 1 second. |
|---|
| | 2666 | +/ |
|---|
| | 2667 | this(int hnsecs) pure |
|---|
| | 2668 | { |
|---|
| | 2669 | _enforceValid(hnsecs); |
|---|
| | 2670 | _hnsecs = hnsecs; |
|---|
| | 2671 | } |
|---|
| | 2672 | |
|---|
| | 2673 | |
|---|
| | 2674 | pure invariant() |
|---|
| | 2675 | { |
|---|
| | 2676 | if(!_valid(_hnsecs)) |
|---|
| | 2677 | throw new AssertError("Invaliant Failure: hnsecs [" ~ numToString(_hnsecs) ~ "]", __FILE__, __LINE__); |
|---|
| | 2678 | } |
|---|
| | 2679 | |
|---|
| | 2680 | |
|---|
| | 2681 | int _hnsecs; |
|---|
| | 2682 | } |
|---|
| | 2683 | |
|---|
| | 2684 | |
|---|
| | 2685 | /++ |
|---|
| | 2686 | Exception type used by core.time. |
|---|
| | 2687 | +/ |
|---|
| | 2688 | class TimeException : Exception |
|---|
| | 2689 | { |
|---|
| | 2690 | /++ |
|---|
| | 2691 | Params: |
|---|
| | 2692 | msg = The message for the exception. |
|---|
| | 2693 | file = The file where the exception occurred. |
|---|
| | 2694 | line = The line number where the exception occurred. |
|---|
| | 2695 | next = The previous exception in the chain of exceptions, if any. |
|---|
| | 2696 | +/ |
|---|
| | 2697 | this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) nothrow |
|---|
| | 2698 | { |
|---|
| | 2699 | super(msg, file, line, next); |
|---|
| | 2700 | } |
|---|
| | 2701 | } |
|---|
| | 2702 | |
|---|
| | 2703 | |
|---|
| | 2704 | //============================================================================== |
|---|
| | 2705 | // Private Section. |
|---|
| | 2706 | // |
|---|
| | 2707 | // Much of this is a copy or simplified copy of what's in std.datetime. |
|---|
| | 2708 | //============================================================================== |
|---|
| | 2709 | private: |
|---|
| | 2710 | |
|---|
| | 2711 | |
|---|
| | 2712 | /+ |
|---|
| | 2713 | Template to help with converting between time units. |
|---|
| | 2714 | +/ |
|---|
| | 2715 | template hnsecsPer(string units) |
|---|
| | 2716 | if(units == "weeks" || |
|---|
| | 2717 | units == "days" || |
|---|
| | 2718 | units == "hours" || |
|---|
| | 2719 | units == "minutes" || |
|---|
| | 2720 | units == "seconds" || |
|---|
| | 2721 | units == "msecs" || |
|---|
| | 2722 | units == "usecs" || |
|---|
| | 2723 | units == "hnsecs") |
|---|
| | 2724 | { |
|---|
| | 2725 | static if(units == "hnsecs") |
|---|
| | 2726 | enum hnsecsPer = 1L; |
|---|
| | 2727 | else static if(units == "usecs") |
|---|
| | 2728 | enum hnsecsPer = 10L; |
|---|
| | 2729 | else static if(units == "msecs") |
|---|
| | 2730 | enum hnsecsPer = 1000 * hnsecsPer!"usecs"; |
|---|
| | 2731 | else static if(units == "seconds") |
|---|
| | 2732 | enum hnsecsPer = 1000 * hnsecsPer!"msecs"; |
|---|
| | 2733 | else static if(units == "minutes") |
|---|
| | 2734 | enum hnsecsPer = 60 * hnsecsPer!"seconds"; |
|---|
| | 2735 | else static if(units == "hours") |
|---|
| | 2736 | enum hnsecsPer = 60 * hnsecsPer!"minutes"; |
|---|
| | 2737 | else static if(units == "days") |
|---|
| | 2738 | enum hnsecsPer = 24 * hnsecsPer!"hours"; |
|---|
| | 2739 | else static if(units == "weeks") |
|---|
| | 2740 | enum hnsecsPer = 7 * hnsecsPer!"days"; |
|---|
| | 2741 | } |
|---|
| | 2742 | |
|---|
| | 2743 | /+ |
|---|
| | 2744 | Splits out a particular unit from hnsecs and gives you the value for that |
|---|
| | 2745 | unit and the remaining hnsecs. It really shouldn't be used unless unless |
|---|
| | 2746 | all units larger than the given units have already been split out. |
|---|
| | 2747 | |
|---|
| | 2748 | Params: |
|---|
| | 2749 | units = The units to split out. |
|---|
| | 2750 | hnsecs = The current total hnsecs. Upon returning, it is the hnsecs left |
|---|
| | 2751 | after splitting out the given units. |
|---|
| | 2752 | |
|---|
| | 2753 | Returns: |
|---|
| | 2754 | The number of the given units from converting hnsecs to those units. |
|---|
| | 2755 | |
|---|
| | 2756 | Examples: |
|---|
| | 2757 | -------------------- |
|---|
| | 2758 | auto hnsecs = 2595000000007L; |
|---|
| | 2759 | immutable days = splitUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 2760 | assert(days == 3); |
|---|
| | 2761 | assert(hnsecs == 3000000007); |
|---|
| | 2762 | |
|---|
| | 2763 | immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs); |
|---|
| | 2764 | assert(minutes == 5); |
|---|
| | 2765 | assert(hnsecs == 7); |
|---|
| | 2766 | -------------------- |
|---|
| | 2767 | +/ |
|---|
| | 2768 | long splitUnitsFromHNSecs(string units)(ref long hnsecs) pure nothrow |
|---|
| | 2769 | if(units == "weeks" || |
|---|
| | 2770 | units == "days" || |
|---|
| | 2771 | units == "hours" || |
|---|
| | 2772 | units == "minutes" || |
|---|
| | 2773 | units == "seconds" || |
|---|
| | 2774 | units == "msecs" || |
|---|
| | 2775 | units == "usecs" || |
|---|
| | 2776 | units == "hnsecs") |
|---|
| | 2777 | { |
|---|
| | 2778 | immutable value = convert!("hnsecs", units)(hnsecs); |
|---|
| | 2779 | hnsecs -= convert!(units, "hnsecs")(value); |
|---|
| | 2780 | |
|---|
| | 2781 | return value; |
|---|
| | 2782 | } |
|---|
| | 2783 | |
|---|
| | 2784 | unittest |
|---|
| | 2785 | { |
|---|
| | 2786 | //Verify Example. |
|---|
| | 2787 | auto hnsecs = 2595000000007L; |
|---|
| | 2788 | immutable days = splitUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 2789 | assert(days == 3); |
|---|
| | 2790 | assert(hnsecs == 3000000007); |
|---|
| | 2791 | |
|---|
| | 2792 | immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs); |
|---|
| | 2793 | assert(minutes == 5); |
|---|
| | 2794 | assert(hnsecs == 7); |
|---|
| | 2795 | } |
|---|
| | 2796 | |
|---|
| | 2797 | |
|---|
| | 2798 | /+ |
|---|
| | 2799 | This function is used to split out the units without getting the remaining |
|---|
| | 2800 | hnsecs. |
|---|
| | 2801 | |
|---|
| | 2802 | See_Also: |
|---|
| | 2803 | splitUnitsFromHNSecs() |
|---|
| | 2804 | |
|---|
| | 2805 | Params: |
|---|
| | 2806 | units = The units to split out. |
|---|
| | 2807 | hnsecs = The current total hnsecs. |
|---|
| | 2808 | |
|---|
| | 2809 | Returns: |
|---|
| | 2810 | The split out value. |
|---|
| | 2811 | |
|---|
| | 2812 | Examples: |
|---|
| | 2813 | -------------------- |
|---|
| | 2814 | auto hnsecs = 2595000000007L; |
|---|
| | 2815 | immutable days = getUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 2816 | assert(days == 3); |
|---|
| | 2817 | assert(hnsecs == 2595000000007L); |
|---|
| | 2818 | -------------------- |
|---|
| | 2819 | +/ |
|---|
| | 2820 | long getUnitsFromHNSecs(string units)(long hnsecs) pure nothrow |
|---|
| | 2821 | if(units == "weeks" || |
|---|
| | 2822 | units == "days" || |
|---|
| | 2823 | units == "hours" || |
|---|
| | 2824 | units == "minutes" || |
|---|
| | 2825 | units == "seconds" || |
|---|
| | 2826 | units == "msecs" || |
|---|
| | 2827 | units == "usecs" || |
|---|
| | 2828 | units == "hnsecs") |
|---|
| | 2829 | { |
|---|
| | 2830 | return convert!("hnsecs", units)(hnsecs); |
|---|
| | 2831 | } |
|---|
| | 2832 | |
|---|
| | 2833 | unittest |
|---|
| | 2834 | { |
|---|
| | 2835 | //Verify Example. |
|---|
| | 2836 | auto hnsecs = 2595000000007L; |
|---|
| | 2837 | immutable days = getUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 2838 | assert(days == 3); |
|---|
| | 2839 | assert(hnsecs == 2595000000007L); |
|---|
| | 2840 | } |
|---|
| | 2841 | |
|---|
| | 2842 | |
|---|
| | 2843 | /+ |
|---|
| | 2844 | This function is used to split out the units without getting the units but |
|---|
| | 2845 | just the remaining hnsecs. |
|---|
| | 2846 | |
|---|
| | 2847 | See_Also: |
|---|
| | 2848 | splitUnitsFromHNSecs() |
|---|
| | 2849 | |
|---|
| | 2850 | Params: |
|---|
| | 2851 | units = The units to split out. |
|---|
| | 2852 | hnsecs = The current total hnsecs. |
|---|
| | 2853 | |
|---|
| | 2854 | Returns: |
|---|
| | 2855 | The remaining hnsecs. |
|---|
| | 2856 | |
|---|
| | 2857 | Examples: |
|---|
| | 2858 | -------------------- |
|---|
| | 2859 | auto hnsecs = 2595000000007L; |
|---|
| | 2860 | auto returned = removeUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 2861 | assert(returned == 3000000007); |
|---|
| | 2862 | assert(hnsecs == 2595000000007L); |
|---|
| | 2863 | -------------------- |
|---|
| | 2864 | +/ |
|---|
| | 2865 | long removeUnitsFromHNSecs(string units)(long hnsecs) pure nothrow |
|---|
| | 2866 | if(units == "weeks" || |
|---|
| | 2867 | units == "days" || |
|---|
| | 2868 | units == "hours" || |
|---|
| | 2869 | units == "minutes" || |
|---|
| | 2870 | units == "seconds" || |
|---|
| | 2871 | units == "msecs" || |
|---|
| | 2872 | units == "usecs" || |
|---|
| | 2873 | units == "hnsecs") |
|---|
| | 2874 | { |
|---|
| | 2875 | immutable value = convert!("hnsecs", units)(hnsecs); |
|---|
| | 2876 | |
|---|
| | 2877 | return hnsecs - convert!(units, "hnsecs")(value); |
|---|
| | 2878 | } |
|---|
| | 2879 | |
|---|
| | 2880 | unittest |
|---|
| | 2881 | { |
|---|
| | 2882 | //Verify Example. |
|---|
| | 2883 | auto hnsecs = 2595000000007L; |
|---|
| | 2884 | auto returned = removeUnitsFromHNSecs!"days"(hnsecs); |
|---|
| | 2885 | assert(returned == 3000000007); |
|---|
| | 2886 | assert(hnsecs == 2595000000007L); |
|---|
| | 2887 | } |
|---|
| | 2888 | |
|---|
| | 2889 | |
|---|
| | 2890 | /++ |
|---|
| | 2891 | Whether all of the given strings are valid units of time. |
|---|
| | 2892 | +/ |
|---|
| | 2893 | bool validTimeUnits(string[] units...) |
|---|
| | 2894 | { |
|---|
| | 2895 | foreach(str; units) |
|---|
| | 2896 | { |
|---|
| | 2897 | switch(str) |
|---|
| | 2898 | { |
|---|
| | 2899 | case "years": |
|---|
| | 2900 | case "months": |
|---|
| | 2901 | case "weeks": |
|---|
| | 2902 | case "days": |
|---|
| | 2903 | case "hours": |
|---|
| | 2904 | case "minutes": |
|---|
| | 2905 | case "seconds": |
|---|
| | 2906 | case "msecs": |
|---|
| | 2907 | case "usecs": |
|---|
| | 2908 | case "hnsecs": |
|---|
| | 2909 | return true; |
|---|
| | 2910 | default: |
|---|
| | 2911 | return false; |
|---|
| | 2912 | } |
|---|
| | 2913 | } |
|---|
| | 2914 | |
|---|
| | 2915 | return false; |
|---|
| | 2916 | } |
|---|
| | 2917 | |
|---|
| | 2918 | |
|---|
| | 2919 | /+ |
|---|
| | 2920 | The time units which are one step larger than the given units. |
|---|
| | 2921 | |
|---|
| | 2922 | Examples: |
|---|
| | 2923 | -------------------- |
|---|
| | 2924 | assert(nextLargerTimeUnits!"minutes" == "hours"); |
|---|
| | 2925 | assert(nextLargerTimeUnits!"hnsecs" == "usecs"); |
|---|
| | 2926 | -------------------- |
|---|
| | 2927 | +/ |
|---|
| | 2928 | template nextLargerTimeUnits(string units) |
|---|
| | 2929 | if(units == "days" || |
|---|
| | 2930 | units == "hours" || |
|---|
| | 2931 | units == "minutes" || |
|---|
| | 2932 | units == "seconds" || |
|---|
| | 2933 | units == "msecs" || |
|---|
| | 2934 | units == "usecs" || |
|---|
| | 2935 | units == "hnsecs" || |
|---|
| | 2936 | units == "nsecs") |
|---|
| | 2937 | { |
|---|
| | 2938 | static if(units == "days") |
|---|
| | 2939 | enum nextLargerTimeUnits = "weeks"; |
|---|
| | 2940 | else static if(units == "hours") |
|---|
| | 2941 | enum nextLargerTimeUnits = "days"; |
|---|
| | 2942 | else static if(units == "minutes") |
|---|
| | 2943 | enum nextLargerTimeUnits = "hours"; |
|---|
| | 2944 | else static if(units == "seconds") |
|---|
| | 2945 | enum nextLargerTimeUnits = "minutes"; |
|---|
| | 2946 | else static if(units == "msecs") |
|---|
| | 2947 | enum nextLargerTimeUnits = "seconds"; |
|---|
| | 2948 | else static if(units == "usecs") |
|---|
| | 2949 | enum nextLargerTimeUnits = "msecs"; |
|---|
| | 2950 | else static if(units == "hnsecs") |
|---|
| | 2951 | enum nextLargerTimeUnits = "usecs"; |
|---|
| | 2952 | else static if(units == "nsecs") |
|---|
| | 2953 | enum nextLargerTimeUnits = "hnsecs"; |
|---|
| | 2954 | else |
|---|
| | 2955 | static assert(0, "Broken template constraint"); |
|---|
| | 2956 | } |
|---|
| | 2957 | |
|---|
| | 2958 | unittest |
|---|
| | 2959 | { |
|---|
| | 2960 | assert(nextLargerTimeUnits!"nsecs" == "hnsecs"); |
|---|
| | 2961 | assert(nextLargerTimeUnits!"hnsecs" == "usecs"); |
|---|
| | 2962 | assert(nextLargerTimeUnits!"usecs" == "msecs"); |
|---|
| | 2963 | assert(nextLargerTimeUnits!"msecs" == "seconds"); |
|---|
| | 2964 | assert(nextLargerTimeUnits!"seconds" == "minutes"); |
|---|
| | 2965 | assert(nextLargerTimeUnits!"minutes" == "hours"); |
|---|
| | 2966 | assert(nextLargerTimeUnits!"hours" == "days"); |
|---|
| | 2967 | assert(nextLargerTimeUnits!"days" == "weeks"); |
|---|
| | 2968 | |
|---|
| | 2969 | static assert(!__traits(compiles, nextLargerTimeUnits!"weeks")); |
|---|
| | 2970 | static assert(!__traits(compiles, nextLargerTimeUnits!"months")); |
|---|
| | 2971 | static assert(!__traits(compiles, nextLargerTimeUnits!"years")); |
|---|
| | 2972 | |
|---|
| | 2973 | //Verify Examples |
|---|
| | 2974 | assert(nextLargerTimeUnits!"minutes" == "hours"); |
|---|
| | 2975 | assert(nextLargerTimeUnits!"hnsecs" == "usecs"); |
|---|
| | 2976 | } |
|---|
| | 2977 | |
|---|
| | 2978 | |
|---|
| | 2979 | /++ |
|---|
| | 2980 | Unfortunately, snprintf is not pure, so here's a way to convert |
|---|
| | 2981 | a number to a string which is. |
|---|
| | 2982 | +/ |
|---|
| | 2983 | string numToString(long value) pure nothrow |
|---|
| | 2984 | { |
|---|
| | 2985 | try |
|---|
| | 2986 | { |
|---|
| | 2987 | immutable negative = value < 0; |
|---|
| | 2988 | char[25] str; |
|---|
| | 2989 | size_t i = str.length; |
|---|
| | 2990 | |
|---|
| | 2991 | if(negative) |
|---|
| | 2992 | value = -value; |
|---|
| | 2993 | |
|---|
| | 2994 | while(1) |
|---|
| | 2995 | { |
|---|
| | 2996 | char digit = cast(char)('0' + value % 10); |
|---|
| | 2997 | value /= 10; |
|---|
| | 2998 | |
|---|
| | 2999 | str[--i] = digit; |
|---|
| | 3000 | assert(i > 0); |
|---|
| | 3001 | |
|---|
| | 3002 | if(value == 0) |
|---|
| | 3003 | break; |
|---|
| | 3004 | } |
|---|
| | 3005 | |
|---|
| | 3006 | if(negative) |
|---|
| | 3007 | return "-" ~ str[i .. $].idup; |
|---|