/spec/aef/weekling/week_day_spec.rb

https://gitlab.com/weekling/weekling · Ruby · 623 lines · 488 code · 117 blank · 18 comment · 13 complexity · aa21e0d90cf6a2d0eb52002faf3387f2 MD5 · raw file

  1. # encoding: UTF-8
  2. =begin
  3. Copyright Alexander E. Fischer <aef@raxys.net>, 2012
  4. This file is part of Weekling.
  5. Permission to use, copy, modify, and/or distribute this software for any
  6. purpose with or without fee is hereby granted, provided that the above
  7. copyright notice and this permission notice appear in all copies.
  8. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  9. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  10. FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  13. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. PERFORMANCE OF THIS SOFTWARE.
  15. =end
  16. require 'spec_helper'
  17. require 'aef/weekling/week_day'
  18. require 'ostruct'
  19. describe Aef::Weekling::WeekDay do
  20. [:today, :now].each do |method|
  21. context ".#{method}" do
  22. it "should generate a representation of the current day as week day" do
  23. today = Date.today
  24. week_day = described_class.method(method).call
  25. week_day.week.year.should eql Aef::Weekling::Year.new(today.year)
  26. week_day.week.index.should eql today.cweek
  27. week_day.index.should eql ((today.wday - 1) % 7) + 1
  28. end
  29. end
  30. end
  31. context ".parse" do
  32. it "should recognize an ancient week day" do
  33. week_day = described_class.parse('-1503-W50-6')
  34. week_day.week.should eql Aef::Weekling::Week.new(-1503, 50)
  35. week_day.index.should eql 6
  36. end
  37. it "should recognize a normal week day" do
  38. week_day = described_class.parse('2011-W30-1')
  39. week_day.week.should eql Aef::Weekling::Week.new(2011, 30)
  40. week_day.index.should eql 1
  41. end
  42. it "should recognize a post apocalyptic week day" do
  43. week_day = described_class.parse('50023-W03-7')
  44. week_day.week.should eql Aef::Weekling::Week.new(50023, 3)
  45. week_day.index.should eql 7
  46. end
  47. it "should report being unable to parse the given String" do
  48. lambda{
  49. described_class.parse('no week day!')
  50. }.should raise_error(ArgumentError, 'No week day found for parsing')
  51. end
  52. end
  53. context ".new" do
  54. it "should complain about a param of invalid type" do
  55. lambda {
  56. described_class.new(123)
  57. }.should raise_error(ArgumentError, 'A single argument must either respond to #week and #index or to #to_date')
  58. end
  59. it "should complain about less than one argument" do
  60. lambda {
  61. described_class.new
  62. }.should raise_error(ArgumentError, 'wrong number of arguments (0 for 1..3)')
  63. end
  64. it "should complain about more than three arguments" do
  65. lambda {
  66. described_class.new(123, 456, 789, 123)
  67. }.should raise_error(ArgumentError, 'wrong number of arguments (4 for 1..3)')
  68. end
  69. it "should allow to create a weekday by a given year, week index and day index" do
  70. week_day = described_class.new(2011, 1, 6)
  71. week_day.week.should eql Aef::Weekling::Week.new(2011, 1)
  72. week_day.index.should eql 6
  73. end
  74. it "should allow to create a weekday by a given year, week index and day symbol" do
  75. week_day = described_class.new(2011, 1, :saturday)
  76. week_day.week.should eql Aef::Weekling::Week.new(2011, 1)
  77. week_day.index.should eql 6
  78. end
  79. it "should allow to create a weekday by a given WeekDay object" do
  80. old_week_day = described_class.new(2011, 1, 6)
  81. week_day = described_class.new(old_week_day)
  82. week_day.week.should eql Aef::Weekling::Week.new(2011, 1)
  83. week_day.index.should eql 6
  84. end
  85. it "should allow to create a weekday by a given Week object and day index" do
  86. week_day = described_class.new(Aef::Weekling::Week.new(2011, 1), 3)
  87. week_day.week.should eql Aef::Weekling::Week.new(2011, 1)
  88. week_day.index.should eql 3
  89. end
  90. it "should allow to create a weekday by a given Week object and day symbol" do
  91. week_day = described_class.new(Aef::Weekling::Week.new(2011, 1), :wednesday)
  92. week_day.week.should eql Aef::Weekling::Week.new(2011, 1)
  93. week_day.index.should eql 3
  94. end
  95. it "should allow to create a weekday by a given Date object" do
  96. date = Date.new(2011, 4, 6)
  97. week_day = described_class.new(date)
  98. week_day.week.should eql Aef::Weekling::Week.new(2011, 14)
  99. week_day.index.should eql 3
  100. end
  101. it "should be able to initialize a weekday within the last week of a year by a given Date object which is already in the following year" do
  102. date = Date.new(1802, 1, 1)
  103. week_day = described_class.new(date)
  104. week_day.week.should eql Aef::Weekling::Week.new(1801, 53)
  105. week_day.index.should eql 5
  106. end
  107. it "should be able to initialize a weekday within the first week of a year by a given Date object which is still in the previous year" do
  108. date = Date.new(2008, 12, 30)
  109. week_day = described_class.new(date)
  110. week_day.week.should eql Aef::Weekling::Week.new(2009, 1)
  111. week_day.index.should eql 2
  112. end
  113. it "should allow to create a weekday by a given DateTime object" do
  114. datetime = DateTime.parse('2011-04-06T16:45:30')
  115. week_day = described_class.new(datetime)
  116. week_day.week.should eql Aef::Weekling::Week.new(2011, 14)
  117. week_day.index.should eql 3
  118. end
  119. it "should allow to create a weekday by a given Time object" do
  120. datetime = Time.parse('2011-04-06T16:45:30')
  121. week_day = described_class.new(datetime)
  122. week_day.week.should eql Aef::Weekling::Week.new(2011, 14)
  123. week_day.index.should eql 3
  124. end
  125. it "should complain about a day index below 1" do
  126. lambda {
  127. described_class.new(Aef::Weekling::Week.today, 0)
  128. }.should raise_error(ArgumentError)
  129. end
  130. it "should complain about a day index above 7" do
  131. lambda {
  132. described_class.new(Aef::Weekling::Week.today, 8)
  133. }.should raise_error(ArgumentError)
  134. end
  135. it "should complain about an invalid day symbol" do
  136. lambda {
  137. described_class.new(Aef::Weekling::Week.today, :poopsday)
  138. }.should raise_error(ArgumentError)
  139. end
  140. end
  141. context "#== (type independent equality)" do
  142. it "should be true if week and index match" do
  143. week = described_class.new(2012, 1, 3)
  144. other = described_class.new(2012, 1, 3)
  145. week.should == other
  146. end
  147. it "should be true if week and index match, independent of the other object's type" do
  148. week = described_class.new(2012, 1, 3)
  149. other = OpenStruct.new
  150. other.week = Aef::Weekling::Week.new(2012, 1)
  151. other.index = 3
  152. week.should == other
  153. end
  154. it "should be false if week matches but not index" do
  155. week = described_class.new(2012, 1, 2)
  156. other = described_class.new(2012, 1, 4)
  157. week.should_not == other
  158. end
  159. it "should be false if week matches but not index, independent of the other object's type" do
  160. week = described_class.new(2012, 1, 2)
  161. other = OpenStruct.new
  162. other.week = Aef::Weekling::Week.new(2012, 1)
  163. other.index = 4
  164. week.should_not == other
  165. end
  166. it "should be false if index matches but not week" do
  167. week = described_class.new(2011, 15, 1)
  168. other = described_class.new(2011, 17, 1)
  169. week.should_not == other
  170. end
  171. it "should be false if index matches but not week, independent of the other object's type" do
  172. week = described_class.new(2011, 15, 1)
  173. other = OpenStruct.new
  174. other.week = Aef::Weekling::Week.new(2011, 17)
  175. other.index = 1
  176. week.should_not == other
  177. end
  178. it "should be false if both index and week do not match" do
  179. week = described_class.new(2012, 23, 1)
  180. other = described_class.new(2005, 14, 5)
  181. week.should_not == other
  182. end
  183. it "should be false if both index and year do not match, independent of the other object's type" do
  184. week = described_class.new(2012, 23, 1)
  185. other = OpenStruct.new
  186. other.week = Aef::Weekling::Week.new(2005, 14)
  187. other.index = 5
  188. week.should_not == other
  189. end
  190. end
  191. context "#eql? (type dependent equality)" do
  192. it "should be true if week and index match" do
  193. week = described_class.new(2012, 1, 3)
  194. other = described_class.new(2012, 1, 3)
  195. week.should eql other
  196. end
  197. it "should be false if week matches but not index" do
  198. week = described_class.new(2012, 1, 2)
  199. other = described_class.new(2012, 1, 4)
  200. week.should_not eql other
  201. end
  202. it "should be false if index matches but not week" do
  203. week = described_class.new(2011, 15, 1)
  204. other = described_class.new(2011, 17, 1)
  205. week.should_not eql other
  206. end
  207. it "should be false if both index and week do not match" do
  208. week = described_class.new(2012, 23, 1)
  209. other = described_class.new(2005, 14, 4)
  210. week.should_not eql other
  211. end
  212. end
  213. context "#hash" do
  214. it "should return Integers" do
  215. a_week_day = described_class.new(2012, 5, 4)
  216. another_week_day = described_class.new(2012, 5, 5)
  217. a_week_day.hash.should be_a(Integer)
  218. another_week_day.hash.should be_a(Integer)
  219. end
  220. it "should discriminate a week-day from another one" do
  221. a_week_day = described_class.new(2012, 5, 4)
  222. another_week_day = described_class.new(2012, 5, 5)
  223. a_week_day.hash.should_not == another_week_day.hash
  224. end
  225. end
  226. context "#<=>" do
  227. it "should correctly determine the order of week days based on week" do
  228. lower_week_day = described_class.new(2011, 13, 3)
  229. higher_week_day = described_class.new(2012, 50, 3)
  230. lower_week_day.should < higher_week_day
  231. end
  232. it "should correctly determine the order of week days based on year, independent of type" do
  233. lower_week_day = described_class.new(2011, 13, 3)
  234. higher_week_day = OpenStruct.new
  235. higher_week_day.week = Aef::Weekling::Week.new(2012, 50)
  236. higher_week_day.index = 3
  237. lower_week_day.should < higher_week_day
  238. end
  239. it "should correctly determine the order of week days based on index" do
  240. lower_week_day = described_class.new(2011, 15, 2)
  241. higher_week_day = described_class.new(2011, 15, 3)
  242. lower_week_day.should < higher_week_day
  243. end
  244. it "should correctly determine the order of week days based on index, independent of type" do
  245. lower_week_day = described_class.new(2011, 15, 2)
  246. higher_week_day = OpenStruct.new
  247. higher_week_day.week = Aef::Weekling::Week.new(2011, 15)
  248. higher_week_day.index = 3
  249. lower_week_day.should < higher_week_day
  250. end
  251. it "should prioritize the order weeks when determining the order of week days" do
  252. lower_week_day = described_class.new(2012, 13, 4)
  253. higher_week_day = described_class.new(2012, 14, 3)
  254. lower_week_day.should < higher_week_day
  255. end
  256. it "should prioritize the order weeks when determining the order of week days, independent of type" do
  257. lower_week_day = described_class.new(2012, 13, 4)
  258. higher_week_day = OpenStruct.new
  259. higher_week_day.week = Aef::Weekling::Week.new(2012, 14)
  260. higher_week_day.index = 3
  261. lower_week_day.should < higher_week_day
  262. end
  263. end
  264. context "#to_s" do
  265. it "should be able to display an ancient week day" do
  266. week_day = described_class.new(-1503, 50, 3)
  267. week_day.to_s.should eql '-1503-W50-3'
  268. end
  269. it "should be able to display a normal week" do
  270. week_day = described_class.new(2011, 30, 7)
  271. week_day.to_s.should eql '2011-W30-7'
  272. end
  273. it "should be able to display a post apocalyptic week" do
  274. week_day = described_class.new(50023, 3, 1)
  275. week_day.to_s.should eql '50023-W03-1'
  276. end
  277. end
  278. context "#inspect" do
  279. it "should be able to display an ancient week day" do
  280. week_day = described_class.new(-1503, 50, 3)
  281. week_day.inspect.should eql '#<Aef::Weekling::WeekDay: -1503-W50-3>'
  282. end
  283. it "should be able to display a normal week" do
  284. week_day = described_class.new(2011, 30, 7)
  285. week_day.inspect.should eql '#<Aef::Weekling::WeekDay: 2011-W30-7>'
  286. end
  287. it "should be able to display a post apocalyptic week" do
  288. week_day = described_class.new(50023, 3, 1)
  289. week_day.inspect.should eql '#<Aef::Weekling::WeekDay: 50023-W03-1>'
  290. end
  291. end
  292. context "#to_date" do
  293. it "should translate to the Date of the day" do
  294. week_day = described_class.new(2011, 30, 3)
  295. week_day.to_date.should eql Date.new(2011, 7, 27)
  296. end
  297. it "should translate to the Date of the day in edge cases early in the year" do
  298. week_day = described_class.new(2010, 52, 6)
  299. week_day.to_date.should eql Date.new(2011, 1, 1)
  300. end
  301. it "should translate to the Date of the day in edge cases late in the year" do
  302. week_day = described_class.new(2011, 52, 7)
  303. week_day.to_date.should eql Date.new(2012, 1, 1)
  304. end
  305. end
  306. context "#to_week_date" do
  307. it "should return itself" do
  308. week_day = described_class.new(2011, 30, 6)
  309. week_day.to_week_day.should equal(week_day)
  310. end
  311. end
  312. [:next, :succ].each do |method|
  313. context "##{method}" do
  314. it "should return the next week day" do
  315. described_class.new(2011, 19, 3).method(method).call.should eql described_class.new(2011, 19, 4)
  316. end
  317. it "should return the next week day at the end of a week" do
  318. described_class.new(2011, 30, 7).method(method).call.should eql described_class.new(2011, 31, 1)
  319. end
  320. it "should return the next week day at the end of a year with 52 weeks" do
  321. described_class.new(2000, 52, 7).method(method).call.should eql described_class.new(2001, 1, 1)
  322. end
  323. it "should return the next week day at the end of a year with 53 weeks" do
  324. described_class.new(1998, 53, 7).method(method).call.should eql described_class.new(1999, 1, 1)
  325. end
  326. end
  327. end
  328. [:previous, :pred].each do |method|
  329. context "##{method}" do
  330. it "should return the previous week day" do
  331. described_class.new(2011, 20, 3).method(method).call.should eql described_class.new(2011, 20, 2)
  332. end
  333. it "should return the previous week day at the beginning of a week" do
  334. described_class.new(2011, 9, 1).method(method).call.should eql described_class.new(2011, 8, 7)
  335. end
  336. it "should return the previous week day at the beginning of a year following a year with 52 weeks" do
  337. described_class.new(2001, 1, 1).method(method).call.should eql described_class.new(2000, 52, 7)
  338. end
  339. it "should return the previous week day at the beginning of a year following a year with 53 weeks" do
  340. described_class.new(1999, 1, 1).method(method).call.should eql described_class.new(1998, 53, 7)
  341. end
  342. end
  343. end
  344. context "#+" do
  345. it "should be able to add a positive amount of days" do
  346. (described_class.new(1996, 51, 4) + 2).should eql described_class.new(1996, 51, 6)
  347. end
  348. it "should be able to add a positive amount of days so that the result isn't in the week anymore'" do
  349. (described_class.new(1996, 51, 4) + 4).should eql described_class.new(1996, 52, 1)
  350. end
  351. it "should be able to add a positive amount of days so that the result isn't in the year anymore'" do
  352. (described_class.new(1996, 51, 4) + 12).should eql described_class.new(1997, 1, 2)
  353. end
  354. it "should be able to add a positive amount of days so that the result isn't in the year with 53 weeks anymore'" do
  355. (described_class.new(1998, 51, 4) + 20).should eql described_class.new(1999, 1, 3)
  356. end
  357. it "should be able to add a negative amount of days" do
  358. (described_class.new(1996, 2, 4) + -2).should eql described_class.new(1996, 2, 2)
  359. end
  360. it "should be able to add a negative amount of days so that the result isn't in the week anymore'" do
  361. (described_class.new(1996, 2, 4) + -5).should eql described_class.new(1996, 1, 6)
  362. end
  363. it "should be able to add a negative amount of days so that the result isn't in the year anymore'" do
  364. (described_class.new(1996, 2, 4) + -15).should eql described_class.new(1995, 52, 3)
  365. end
  366. it "should be able to add a negative amount of days so that the result is in the previous year with 53 weeks'" do
  367. (described_class.new(1999, 2, 1) + -10).should eql described_class.new(1998, 53, 5)
  368. end
  369. it "should be able to add zero days" do
  370. (described_class.new(1996, 51, 4) + 0).should eql described_class.new(1996, 51, 4)
  371. end
  372. end
  373. context "#-" do
  374. it "should be able to subtract a positive amount of days" do
  375. (described_class.new(1996, 2, 4) - 2).should eql described_class.new(1996, 2, 2)
  376. end
  377. it "should be able to subtract a positive amount of days so that the result isn't in the week anymore'" do
  378. (described_class.new(1996, 2, 4) - 5).should eql described_class.new(1996, 1, 6)
  379. end
  380. it "should be able to subtract a positive amount of days so that the result isn't in the year anymore'" do
  381. (described_class.new(1996, 2, 4) - 15).should eql described_class.new(1995, 52, 3)
  382. end
  383. it "should be able to subtract a positive amount of days so that the result is in the previous year with 53 weeks'" do
  384. (described_class.new(1999, 2, 1) - 10).should eql described_class.new(1998, 53, 5)
  385. end
  386. it "should be able to subtract a negative amount of days" do
  387. (described_class.new(1996, 51, 4) - -2).should eql described_class.new(1996, 51, 6)
  388. end
  389. it "should be able to subtract a negative amount of days so that the result isn't in the week anymore'" do
  390. (described_class.new(1996, 51, 4) - -4).should eql described_class.new(1996, 52, 1)
  391. end
  392. it "should be able to subtract a negative amount of days so that the result isn't in the year anymore'" do
  393. (described_class.new(1996, 51, 4) - -12).should eql described_class.new(1997, 1, 2)
  394. end
  395. it "should be able to subtract a negative amount of days so that the result isn't in the year with 53 weeks anymore'" do
  396. (described_class.new(1998, 51, 4) - -20).should eql described_class.new(1999, 1, 3)
  397. end
  398. it "should be able to subtract zero days" do
  399. (described_class.new(1996, 51, 4) - 0).should eql described_class.new(1996, 51, 4)
  400. end
  401. end
  402. context "weekday methods" do
  403. it "should report monday" do
  404. week_day = described_class.new(2011, 17, 1)
  405. week_day.monday?.should be_true
  406. week_day.tuesday?.should be_false
  407. week_day.wednesday?.should be_false
  408. week_day.thursday?.should be_false
  409. week_day.friday?.should be_false
  410. week_day.saturday?.should be_false
  411. week_day.sunday?.should be_false
  412. week_day.weekend?.should be_false
  413. week_day.to_sym.should eql :monday
  414. end
  415. it "should report tuesday" do
  416. week_day = described_class.new(2011, 17, 2)
  417. week_day.monday?.should be_false
  418. week_day.tuesday?.should be_true
  419. week_day.wednesday?.should be_false
  420. week_day.thursday?.should be_false
  421. week_day.friday?.should be_false
  422. week_day.saturday?.should be_false
  423. week_day.sunday?.should be_false
  424. week_day.weekend?.should be_false
  425. week_day.to_sym.should eql :tuesday
  426. end
  427. it "should report wednesday" do
  428. week_day = described_class.new(2011, 17, 3)
  429. week_day.monday?.should be_false
  430. week_day.tuesday?.should be_false
  431. week_day.wednesday?.should be_true
  432. week_day.thursday?.should be_false
  433. week_day.friday?.should be_false
  434. week_day.saturday?.should be_false
  435. week_day.sunday?.should be_false
  436. week_day.weekend?.should be_false
  437. week_day.to_sym.should eql :wednesday
  438. end
  439. it "should report thursday" do
  440. week_day = described_class.new(2011, 17, 4)
  441. week_day.monday?.should be_false
  442. week_day.tuesday?.should be_false
  443. week_day.wednesday?.should be_false
  444. week_day.thursday?.should be_true
  445. week_day.friday?.should be_false
  446. week_day.saturday?.should be_false
  447. week_day.sunday?.should be_false
  448. week_day.weekend?.should be_false
  449. week_day.to_sym.should eql :thursday
  450. end
  451. it "should report friday" do
  452. week_day = described_class.new(2011, 17, 5)
  453. week_day.monday?.should be_false
  454. week_day.tuesday?.should be_false
  455. week_day.wednesday?.should be_false
  456. week_day.thursday?.should be_false
  457. week_day.friday?.should be_true
  458. week_day.saturday?.should be_false
  459. week_day.sunday?.should be_false
  460. week_day.weekend?.should be_false
  461. week_day.to_sym.should eql :friday
  462. end
  463. it "should report saturday" do
  464. week_day = described_class.new(2011, 17, 6)
  465. week_day.monday?.should be_false
  466. week_day.tuesday?.should be_false
  467. week_day.wednesday?.should be_false
  468. week_day.thursday?.should be_false
  469. week_day.friday?.should be_false
  470. week_day.saturday?.should be_true
  471. week_day.sunday?.should be_false
  472. week_day.weekend?.should be_true
  473. week_day.to_sym.should eql :saturday
  474. end
  475. it "should report sunday" do
  476. week_day = described_class.new(2011, 17, 7)
  477. week_day.monday?.should be_false
  478. week_day.tuesday?.should be_false
  479. week_day.wednesday?.should be_false
  480. week_day.thursday?.should be_false
  481. week_day.friday?.should be_false
  482. week_day.saturday?.should be_false
  483. week_day.sunday?.should be_true
  484. week_day.weekend?.should be_true
  485. week_day.to_sym.should eql :sunday
  486. end
  487. end
  488. end