1 /** 2 * Proleptic Gregorian calendar: date ranges 3 * 4 * Copyright: Maxim Freck, 2017. 5 * Authors: Maxim Freck <maxim@freck.pp.ru> 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 */ 8 module pgc.daterange; 9 10 public import pgc.date; 11 12 /*********************************** 13 * An implementation of a ForwardRange for dates. 14 * 15 * Examples: 16 * -------------------- 17 * DateRange(mkDate(20, 3, 2016), mkDate(4, 4, 2016)); //returns the date range between 2016-03-20 and 2016-04-04 18 * DateRange(2, 2016); //return the date range for the Feb. 2016 19 * DateRange(2016); //return the date range for the whole 2016 year 20 * -------------------- 21 */ 22 struct DateRange { 23 private Date frontDate; 24 private Date endDate; 25 26 @disable private this(); 27 28 /// Constructor 29 this(Date start, Date end) @safe 30 { 31 import std.algorithm: max, min; 32 this.frontDate = min(start, end); 33 this.endDate = max(start, end).nextDay; 34 } 35 36 /// ditto 37 this(int month, int year) @safe 38 { 39 this.frontDate = mkDate(1, month, year); 40 this.endDate = mkDate(daysInMonth(month, year), month, year).nextDay; 41 } 42 43 /// ditto 44 this(int year) @safe 45 { 46 this.frontDate = mkDate(1, 1, year); 47 this.endDate = mkDateISO(1, 1, ++year); 48 } 49 50 /// for Range access 51 pure nothrow bool empty() const @safe 52 { 53 return this.frontDate == this.endDate; 54 } 55 56 /// ditto 57 pure nothrow auto front() @safe 58 { 59 return this.frontDate; 60 } 61 62 /// ditto 63 pure void popFront() @safe 64 { 65 if (this.frontDate < this.endDate) this.frontDate = this.frontDate.nextDay; 66 } 67 68 /// ditto 69 auto save() const @safe 70 { 71 return this; 72 } 73 74 /*********************************** 75 * Returns the number of days in a range 76 */ 77 @property @safe pure nothrow auto days() 78 { 79 return daysBetween(this.frontDate, this.endDate); 80 } 81 } 82 83 84 /// 85 @safe unittest 86 { 87 auto Feb2016 = DateRange(2,2016); 88 89 assert(Feb2016.days == 29); 90 91 Feb2016.popFront(); 92 assert(Feb2016.front == mkDate(2, 2, 2016)); 93 }