datetime.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. package httpexpect
  2. import (
  3. "errors"
  4. "time"
  5. )
  6. // DateTime provides methods to inspect attached time.Time value.
  7. type DateTime struct {
  8. noCopy noCopy
  9. chain *chain
  10. value time.Time
  11. }
  12. // NewDateTime returns a new DateTime instance.
  13. //
  14. // If reporter is nil, the function panics.
  15. //
  16. // Example:
  17. //
  18. // dt := NewDateTime(t, time.Now())
  19. // dt.Le(time.Now())
  20. //
  21. // time.Sleep(time.Second)
  22. // dt.Lt(time.Now())
  23. func NewDateTime(reporter Reporter, value time.Time) *DateTime {
  24. return newDateTime(newChainWithDefaults("DateTime()", reporter), value)
  25. }
  26. // NewDateTimeC returns a new DateTime instance with config.
  27. //
  28. // Requirements for config are same as for WithConfig function.
  29. //
  30. // See NewDateTime for usage example.
  31. func NewDateTimeC(config Config, value time.Time) *DateTime {
  32. return newDateTime(newChainWithConfig("DateTime()", config.withDefaults()), value)
  33. }
  34. func newDateTime(parent *chain, val time.Time) *DateTime {
  35. return &DateTime{chain: parent.clone(), value: val}
  36. }
  37. // Raw returns underlying time.Time value attached to DateTime.
  38. // This is the value originally passed to NewDateTime.
  39. //
  40. // Example:
  41. //
  42. // dt := NewDateTime(t, timestamp)
  43. // assert.Equal(t, timestamp, dt.Raw())
  44. func (dt *DateTime) Raw() time.Time {
  45. return dt.value
  46. }
  47. // Alias is similar to Value.Alias.
  48. func (dt *DateTime) Alias(name string) *DateTime {
  49. opChain := dt.chain.enter("Alias(%q)", name)
  50. defer opChain.leave()
  51. dt.chain.setAlias(name)
  52. return dt
  53. }
  54. // Zone returns a new String instance with datetime zone.
  55. //
  56. // Example:
  57. //
  58. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  59. // dt := NewDateTime(t, tm)
  60. // dt.Zone().IsEqual("IST")
  61. func (dt *DateTime) Zone() *String {
  62. opChain := dt.chain.enter("Zone()")
  63. defer opChain.leave()
  64. if opChain.failed() {
  65. return newString(opChain, "")
  66. }
  67. zone, _ := dt.value.Zone()
  68. return newString(opChain, zone)
  69. }
  70. // Year returns the year in which datetime occurs,
  71. // in the range [0, 9999]
  72. //
  73. // Example:
  74. //
  75. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  76. // dt := NewDateTime(t, tm)
  77. // dt.Year().IsEqual(2022)
  78. func (dt *DateTime) Year() *Number {
  79. opChain := dt.chain.enter("Year()")
  80. defer opChain.leave()
  81. if opChain.failed() {
  82. return newNumber(opChain, float64(0))
  83. }
  84. return newNumber(opChain, float64(dt.value.Year()))
  85. }
  86. // Month returns the month of the year specified by datetime,
  87. // in the range [1,12].
  88. //
  89. // Example:
  90. //
  91. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  92. // dt := NewDateTime(t, tm)
  93. // dt.Month().IsEqual(12)
  94. func (dt *DateTime) Month() *Number {
  95. opChain := dt.chain.enter("Month()")
  96. defer opChain.leave()
  97. if opChain.failed() {
  98. return newNumber(opChain, float64(0))
  99. }
  100. return newNumber(opChain, float64(dt.value.Month()))
  101. }
  102. // Day returns the day of the month specified datetime,
  103. // in the range [1,31].
  104. //
  105. // Example:
  106. //
  107. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  108. // dt := NewDateTime(t, tm)
  109. // dt.Day().IsEqual(30)
  110. func (dt *DateTime) Day() *Number {
  111. opChain := dt.chain.enter("Day()")
  112. defer opChain.leave()
  113. if opChain.failed() {
  114. return newNumber(opChain, float64(0))
  115. }
  116. return newNumber(opChain, float64(dt.value.Day()))
  117. }
  118. // Weekday returns the day of the week specified by datetime,
  119. // in the range [0, 6], 0 corresponds to Sunday
  120. //
  121. // Example:
  122. //
  123. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  124. // dt := NewDateTime(t, tm)
  125. // dt.WeekDay().IsEqual(time.Friday)
  126. func (dt *DateTime) WeekDay() *Number {
  127. opChain := dt.chain.enter("WeekDay()")
  128. defer opChain.leave()
  129. if opChain.failed() {
  130. return newNumber(opChain, float64(0))
  131. }
  132. return newNumber(opChain, float64(dt.value.Weekday()))
  133. }
  134. // YearDay returns the day of the year specified by datetime,
  135. // in the range [1,365] for non-leap years,
  136. // and [1,366] in leap years.
  137. //
  138. // Example:
  139. //
  140. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  141. // dt := NewDateTime(t, tm)
  142. // dt.YearDay().IsEqual(364)
  143. func (dt *DateTime) YearDay() *Number {
  144. opChain := dt.chain.enter("YearDay()")
  145. defer opChain.leave()
  146. if opChain.failed() {
  147. return newNumber(opChain, float64(0))
  148. }
  149. return newNumber(opChain, float64(dt.value.YearDay()))
  150. }
  151. // Hour returns the hour within the day specified by datetime,
  152. // in the range [0, 23].
  153. //
  154. // Example:
  155. //
  156. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  157. // dt := NewDateTime(t, tm)
  158. // dt.Hour().IsEqual(15)
  159. func (dt *DateTime) Hour() *Number {
  160. opChain := dt.chain.enter("Hour()")
  161. defer opChain.leave()
  162. if opChain.failed() {
  163. return newNumber(opChain, float64(0))
  164. }
  165. return newNumber(opChain, float64(dt.value.Hour()))
  166. }
  167. // Minute returns the minute offset within the hour specified by datetime,
  168. // in the range [0, 59].
  169. //
  170. // Example:
  171. //
  172. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  173. // dt := NewDateTime(t, tm)
  174. // dt.Minute().IsEqual(4)
  175. func (dt *DateTime) Minute() *Number {
  176. opChain := dt.chain.enter("Minute()")
  177. defer opChain.leave()
  178. if opChain.failed() {
  179. return newNumber(opChain, float64(0))
  180. }
  181. return newNumber(opChain, float64(dt.value.Minute()))
  182. }
  183. // Second returns the second offset within the minute specified by datetime,
  184. // in the range [0, 59].
  185. //
  186. // Example:
  187. //
  188. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  189. // dt := NewDateTime(t, tm)
  190. // dt.Second().IsEqual(5)
  191. func (dt *DateTime) Second() *Number {
  192. opChain := dt.chain.enter("Second()")
  193. defer opChain.leave()
  194. if opChain.failed() {
  195. return newNumber(opChain, float64(0))
  196. }
  197. return newNumber(opChain, float64(dt.value.Second()))
  198. }
  199. // Nanosecond returns the nanosecond offset within the second specified by datetime,
  200. // in the range [0, 999999999].
  201. //
  202. // Example:
  203. //
  204. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  205. // dt := NewDateTime(t, tm)
  206. // dt.Nanosecond().IsEqual(0)
  207. func (dt *DateTime) Nanosecond() *Number {
  208. opChain := dt.chain.enter("Nanosecond()")
  209. defer opChain.leave()
  210. if opChain.failed() {
  211. return newNumber(opChain, float64(0))
  212. }
  213. return newNumber(opChain, float64(dt.value.Nanosecond()))
  214. }
  215. // Deprecated: use Zone instead.
  216. func (dt *DateTime) GetZone() *String {
  217. return dt.Zone()
  218. }
  219. // Deprecated: use Year instead.
  220. func (dt *DateTime) GetYear() *Number {
  221. return dt.Year()
  222. }
  223. // Deprecated: use Month instead.
  224. func (dt *DateTime) GetMonth() *Number {
  225. return dt.Month()
  226. }
  227. // Deprecated: use Day instead.
  228. func (dt *DateTime) GetDay() *Number {
  229. return dt.Day()
  230. }
  231. // Deprecated: use WeekDay instead.
  232. func (dt *DateTime) GetWeekDay() *Number {
  233. return dt.WeekDay()
  234. }
  235. // Deprecated: use YearDay instead.
  236. func (dt *DateTime) GetYearDay() *Number {
  237. return dt.YearDay()
  238. }
  239. // Deprecated: use Hour instead.
  240. func (dt *DateTime) GetHour() *Number {
  241. return dt.Hour()
  242. }
  243. // Deprecated: use Minute instead.
  244. func (dt *DateTime) GetMinute() *Number {
  245. return dt.Minute()
  246. }
  247. // Deprecated: use Second instead.
  248. func (dt *DateTime) GetSecond() *Number {
  249. return dt.Second()
  250. }
  251. // Deprecated: use Nanosecond instead.
  252. func (dt *DateTime) GetNanosecond() *Number {
  253. return dt.Nanosecond()
  254. }
  255. // IsEqual succeeds if DateTime is equal to given value.
  256. //
  257. // Example:
  258. //
  259. // dt := NewDateTime(t, time.Unix(0, 1))
  260. // dt.IsEqual(time.Unix(0, 1))
  261. func (dt *DateTime) IsEqual(value time.Time) *DateTime {
  262. opChain := dt.chain.enter("IsEqual()")
  263. defer opChain.leave()
  264. if opChain.failed() {
  265. return dt
  266. }
  267. if !dt.value.Equal(value) {
  268. opChain.fail(AssertionFailure{
  269. Type: AssertEqual,
  270. Actual: &AssertionValue{dt.value},
  271. Expected: &AssertionValue{value},
  272. Errors: []error{
  273. errors.New("expected: time points are equal"),
  274. },
  275. })
  276. }
  277. return dt
  278. }
  279. // NotEqual succeeds if DateTime is not equal to given value.
  280. //
  281. // Example:
  282. //
  283. // dt := NewDateTime(t, time.Unix(0, 1))
  284. // dt.NotEqual(time.Unix(0, 2))
  285. func (dt *DateTime) NotEqual(value time.Time) *DateTime {
  286. opChain := dt.chain.enter("NotEqual()")
  287. defer opChain.leave()
  288. if opChain.failed() {
  289. return dt
  290. }
  291. if dt.value.Equal(value) {
  292. opChain.fail(AssertionFailure{
  293. Type: AssertNotEqual,
  294. Actual: &AssertionValue{dt.value},
  295. Expected: &AssertionValue{value},
  296. Errors: []error{
  297. errors.New("expected: time points are non-equal"),
  298. },
  299. })
  300. }
  301. return dt
  302. }
  303. // Deprecated: use IsEqual instead.
  304. func (dt *DateTime) Equal(value time.Time) *DateTime {
  305. return dt.IsEqual(value)
  306. }
  307. // InRange succeeds if DateTime is within given range [min; max].
  308. //
  309. // Example:
  310. //
  311. // dt := NewDateTime(t, time.Unix(0, 2))
  312. // dt.InRange(time.Unix(0, 1), time.Unix(0, 3))
  313. // dt.InRange(time.Unix(0, 2), time.Unix(0, 2))
  314. func (dt *DateTime) InRange(min, max time.Time) *DateTime {
  315. opChain := dt.chain.enter("InRange()")
  316. defer opChain.leave()
  317. if opChain.failed() {
  318. return dt
  319. }
  320. if !((dt.value.After(min) || dt.value.Equal(min)) &&
  321. (dt.value.Before(max) || dt.value.Equal(max))) {
  322. opChain.fail(AssertionFailure{
  323. Type: AssertInRange,
  324. Actual: &AssertionValue{dt.value},
  325. Expected: &AssertionValue{AssertionRange{min, max}},
  326. Errors: []error{
  327. errors.New("expected: time point is within given range"),
  328. },
  329. })
  330. }
  331. return dt
  332. }
  333. // NotInRange succeeds if DateTime is not within given range [min; max].
  334. //
  335. // Example:
  336. //
  337. // dt := NewDateTime(t, time.Unix(0, 10))
  338. // dt.NotInRange(time.Unix(0, 1), time.Unix(0, 9))
  339. // dt.NotInRange(time.Unix(0, 11), time.Unix(0, 20))
  340. func (dt *DateTime) NotInRange(min, max time.Time) *DateTime {
  341. opChain := dt.chain.enter("NotInRange()")
  342. defer opChain.leave()
  343. if opChain.failed() {
  344. return dt
  345. }
  346. if (dt.value.After(min) || dt.value.Equal(min)) &&
  347. (dt.value.Before(max) || dt.value.Equal(max)) {
  348. opChain.fail(AssertionFailure{
  349. Type: AssertNotInRange,
  350. Actual: &AssertionValue{dt.value},
  351. Expected: &AssertionValue{AssertionRange{min, max}},
  352. Errors: []error{
  353. errors.New("expected: time point is not within given range"),
  354. },
  355. })
  356. }
  357. return dt
  358. }
  359. // InList succeeds if DateTime is equal to one of the values from given
  360. // list of time.Time.
  361. //
  362. // Example:
  363. //
  364. // dt := NewDateTime(t, time.Unix(0, 2))
  365. // dt.InRange(time.Unix(0, 1), time.Unix(0, 2))
  366. func (dt *DateTime) InList(values ...time.Time) *DateTime {
  367. opChain := dt.chain.enter("InList()")
  368. defer opChain.leave()
  369. if opChain.failed() {
  370. return dt
  371. }
  372. if len(values) == 0 {
  373. opChain.fail(AssertionFailure{
  374. Type: AssertUsage,
  375. Errors: []error{
  376. errors.New("unexpected empty list argument"),
  377. },
  378. })
  379. return dt
  380. }
  381. var isListed bool
  382. for _, v := range values {
  383. if dt.value.Equal(v) {
  384. isListed = true
  385. break
  386. }
  387. }
  388. if !isListed {
  389. valueList := make([]interface{}, 0, len(values))
  390. for _, v := range values {
  391. valueList = append(valueList, v)
  392. }
  393. opChain.fail(AssertionFailure{
  394. Type: AssertBelongs,
  395. Actual: &AssertionValue{dt.value},
  396. Expected: &AssertionValue{AssertionList(valueList)},
  397. Errors: []error{
  398. errors.New("expected: time point is equal to one of the values"),
  399. },
  400. })
  401. }
  402. return dt
  403. }
  404. // NotInList succeeds if DateTime is not equal to any of the values from
  405. // given list of time.Time.
  406. //
  407. // Example:
  408. //
  409. // dt := NewDateTime(t, time.Unix(0, 2))
  410. // dt.InRange(time.Unix(0, 1), time.Unix(0, 3))
  411. func (dt *DateTime) NotInList(values ...time.Time) *DateTime {
  412. opChain := dt.chain.enter("NotInList()")
  413. defer opChain.leave()
  414. if opChain.failed() {
  415. return dt
  416. }
  417. if len(values) == 0 {
  418. opChain.fail(AssertionFailure{
  419. Type: AssertUsage,
  420. Errors: []error{
  421. errors.New("unexpected empty list argument"),
  422. },
  423. })
  424. return dt
  425. }
  426. for _, v := range values {
  427. if dt.value.Equal(v) {
  428. valueList := make([]interface{}, 0, len(values))
  429. for _, v := range values {
  430. valueList = append(valueList, v)
  431. }
  432. opChain.fail(AssertionFailure{
  433. Type: AssertNotBelongs,
  434. Actual: &AssertionValue{dt.value},
  435. Expected: &AssertionValue{AssertionList(valueList)},
  436. Errors: []error{
  437. errors.New("expected: time point is not equal to any of the values"),
  438. },
  439. })
  440. return dt
  441. }
  442. }
  443. return dt
  444. }
  445. // Gt succeeds if DateTime is greater than given value.
  446. //
  447. // Example:
  448. //
  449. // dt := NewDateTime(t, time.Unix(0, 2))
  450. // dt.Gt(time.Unix(0, 1))
  451. func (dt *DateTime) Gt(value time.Time) *DateTime {
  452. opChain := dt.chain.enter("Gt()")
  453. defer opChain.leave()
  454. if opChain.failed() {
  455. return dt
  456. }
  457. if !dt.value.After(value) {
  458. opChain.fail(AssertionFailure{
  459. Type: AssertGt,
  460. Actual: &AssertionValue{dt.value},
  461. Expected: &AssertionValue{value},
  462. Errors: []error{
  463. errors.New("expected: time point is after given time"),
  464. },
  465. })
  466. }
  467. return dt
  468. }
  469. // Ge succeeds if DateTime is greater than or equal to given value.
  470. //
  471. // Example:
  472. //
  473. // dt := NewDateTime(t, time.Unix(0, 2))
  474. // dt.Ge(time.Unix(0, 1))
  475. func (dt *DateTime) Ge(value time.Time) *DateTime {
  476. opChain := dt.chain.enter("Ge()")
  477. defer opChain.leave()
  478. if opChain.failed() {
  479. return dt
  480. }
  481. if !(dt.value.After(value) || dt.value.Equal(value)) {
  482. opChain.fail(AssertionFailure{
  483. Type: AssertGe,
  484. Actual: &AssertionValue{dt.value},
  485. Expected: &AssertionValue{value},
  486. Errors: []error{
  487. errors.New("expected: time point is after or equal to given time"),
  488. },
  489. })
  490. }
  491. return dt
  492. }
  493. // Lt succeeds if DateTime is lesser than given value.
  494. //
  495. // Example:
  496. //
  497. // dt := NewDateTime(t, time.Unix(0, 1))
  498. // dt.Lt(time.Unix(0, 2))
  499. func (dt *DateTime) Lt(value time.Time) *DateTime {
  500. opChain := dt.chain.enter("Lt()")
  501. defer opChain.leave()
  502. if opChain.failed() {
  503. return dt
  504. }
  505. if !dt.value.Before(value) {
  506. opChain.fail(AssertionFailure{
  507. Type: AssertLt,
  508. Actual: &AssertionValue{dt.value},
  509. Expected: &AssertionValue{value},
  510. Errors: []error{
  511. errors.New("expected: time point is before given time"),
  512. },
  513. })
  514. }
  515. return dt
  516. }
  517. // Le succeeds if DateTime is lesser than or equal to given value.
  518. //
  519. // Example:
  520. //
  521. // dt := NewDateTime(t, time.Unix(0, 1))
  522. // dt.Le(time.Unix(0, 2))
  523. func (dt *DateTime) Le(value time.Time) *DateTime {
  524. opChain := dt.chain.enter("Le()")
  525. defer opChain.leave()
  526. if opChain.failed() {
  527. return dt
  528. }
  529. if !(dt.value.Before(value) || dt.value.Equal(value)) {
  530. opChain.fail(AssertionFailure{
  531. Type: AssertLe,
  532. Actual: &AssertionValue{dt.value},
  533. Expected: &AssertionValue{value},
  534. Errors: []error{
  535. errors.New("expected: time point is before or equal to given time"),
  536. },
  537. })
  538. }
  539. return dt
  540. }
  541. // AsUTC returns a new DateTime instance in UTC timeZone.
  542. //
  543. // Example:
  544. //
  545. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  546. // dt := NewDateTime(t, tm)
  547. // dt.AsUTC().Zone().IsEqual("UTC")
  548. func (dt *DateTime) AsUTC() *DateTime {
  549. opChain := dt.chain.enter("AsUTC()")
  550. defer opChain.leave()
  551. if opChain.failed() {
  552. return newDateTime(opChain, time.Unix(0, 0))
  553. }
  554. return newDateTime(opChain, dt.value.UTC())
  555. }
  556. // AsLocal returns a new DateTime instance in Local timeZone.
  557. //
  558. // Example:
  559. //
  560. // tm, _ := time.Parse(time.UnixDate, "Fri Dec 30 15:04:05 IST 2022")
  561. // dt := NewDateTime(t, tm)
  562. // dt.AsLocal().Zone().IsEqual("IST")
  563. func (dt *DateTime) AsLocal() *DateTime {
  564. opChain := dt.chain.enter("AsLocal()")
  565. defer opChain.leave()
  566. if opChain.failed() {
  567. return newDateTime(opChain, time.Unix(0, 0))
  568. }
  569. return newDateTime(opChain, dt.value.Local())
  570. }