diff --git a/README b/README index c19c7e388..607bd78e7 100644 --- a/README +++ b/README @@ -1,8 +1 @@ Rating system for telecom providers. - -Match datetime objects instead of timestamp. Example -Year \d{4} #any year -Month \d{2} #any month -Day \d{2} # any day -Hour (0[89]|1\d) #from 08 till 19 -Minute \d{2} diff --git a/timeslots/interval_test.go b/timeslots/interval_test.go new file mode 100644 index 000000000..35d562a51 --- /dev/null +++ b/timeslots/interval_test.go @@ -0,0 +1,124 @@ +package timeslots + +import ( + "time" + "testing" +) + +func TestMonth(t *testing.T){ + i := &Interval{Month: time.February} + d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) + d1 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } +} + +func TestMonthDay(t *testing.T){ + i := &Interval{MonthDay: 10} + d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) + d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } +} + +func TestMonthAndMonthDay(t *testing.T){ + i := &Interval{Month: time.February, MonthDay: 10} + d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) + d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC) + d2 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } + if i.Contains(d2) { + t.Errorf("Date %v shoud not be in interval %v", d2, i) + } +} + +func TestWeekDays(t *testing.T){ + i := &Interval{WeekDays: []time.Weekday{time.Wednesday}} + i2 := &Interval{WeekDays: []time.Weekday{time.Wednesday, time.Thursday}} + d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC) + d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } + if !i2.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i2) + } + if !i2.Contains(d1) { + t.Errorf("Date %v shoud be in interval %v", d1, i2) + } +} + +func TestMonthAndMonthDayAndWeekDays(t *testing.T){ + i := &Interval{Month: time.February, MonthDay: 1, WeekDays: []time.Weekday{time.Wednesday}} + i2 := &Interval{Month: time.February, MonthDay: 2, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}} + d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC) + d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } + if i2.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i2) + } + if !i2.Contains(d1) { + t.Errorf("Date %v shoud be in interval %v", d1, i2) + } +} + +func TestHours(t *testing.T){ + i := &Interval{StartHour: "14:30", EndHour: "15:00"} + d := time.Date(2012, time.February, 10, 14, 30, 0, 0, time.UTC) + d1 := time.Date(2012, time.January, 10, 14, 29, 0, 0, time.UTC) + d2 := time.Date(2012, time.January, 10, 14, 59, 0, 0, time.UTC) + d3 := time.Date(2012, time.January, 10, 15, 01, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } + if !i.Contains(d2) { + t.Errorf("Date %v shoud be in interval %v", d2, i) + } + if i.Contains(d3) { + t.Errorf("Date %v shoud not be in interval %v", d3, i) + } +} + +func TestEverything(t *testing.T){ + i := &Interval{Month: time.February, MonthDay: 1, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartHour: "14:30", EndHour: "15:00"} + d := time.Date(2012, time.February, 1, 14, 30, 0, 0, time.UTC) + d1 := time.Date(2012, time.January, 1, 14, 29, 0, 0, time.UTC) + if !i.Contains(d) { + t.Errorf("Date %v shoud be in interval %v", d, i) + } + if i.Contains(d1) { + t.Errorf("Date %v shoud not be in interval %v", d1, i) + } +} + +func BenchmarkIntervalFull(b *testing.B) { + i := &Interval{Month: time.February, MonthDay: 1, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartHour: "14:30", EndHour: "15:00"} + d := time.Date(2012, time.February, 1, 14, 30, 0, 0, time.UTC) + for x := 0; x < b.N; x++ { + i.Contains(d) + } +} \ No newline at end of file diff --git a/timeslots/timeslots.go b/timeslots/timeslots.go index ad7652374..c7a8b5f89 100644 --- a/timeslots/timeslots.go +++ b/timeslots/timeslots.go @@ -2,6 +2,8 @@ package timeslots import ( "time" + "strings" + "strconv" ) type RatingProfile struct { @@ -9,19 +11,82 @@ type RatingProfile struct { ConnectFee, Price, BillingUnit float32 } +type Interval struct { + Month time.Month + MonthDay int + WeekDays []time.Weekday + StartHour, EndHour string // ##:## format +} + +func (i *Interval) Contains(t time.Time) bool { + // chec for month + if i.Month > 0 && t.Month() != i.Month { + return false + } + // check for month day + if i.MonthDay > 0 && t.Day() != i.MonthDay { + return false + } + // check for weekdays + found := false + for _,wd := range i.WeekDays { + if t.Weekday() == wd { + found = true + } + } + if len(i.WeekDays) > 0 && !found { + return false + } + // check for start hour + if i.StartHour != ""{ + split:= strings.Split(i.StartHour, ":") + sh, _ := strconv.Atoi(split[0]) + sm, _ := strconv.Atoi(split[1]) + // if the hour is before or is the same hour but the minute is before + if t.Hour() < sh || (t.Hour() == sh && t.Minute() < sm) { + return false + } + } + // check for end hour + if i.EndHour != ""{ + split := strings.Split(i.EndHour, ":") + eh, _ := strconv.Atoi(split[0]) + em, _ := strconv.Atoi(split[1]) + // if the hour is after or is the same hour but the minute is after + if t.Hour() > eh || (t.Hour() == eh && t.Minute() > em) { + return false + } + } + return true +} + +func (i *Interval) ContainsSpan(t *TimeSpan) bool { + return i.Contains(t.TimeStart) || i.Contains(t.TimeEnd) +} + +func (i *Interval) ContainsFullSpan(t *TimeSpan) bool { + return i.Contains(t.TimeStart) && i.Contains(t.TimeEnd) +} + +func (i *Interval) Split(t *TimeSpan) (spans []*TimeSpan) { + if !i.ContainsSpan(t) { + return + } + if !i.ContainsFullSpan(t){ + spans = append(spans, t) + } + if !i.Contains(t.TimeStart){ + + spans = append(spans, t) + } + return +} + type ActivationPeriod struct { ActivationTime time.Time RatingProfiles []*RatingProfile } -func (cd *ActivationPeriod) SplitInTimeSpans(t []*ActivationPeriods) (timespans []*TimeSpans) { - for i, ap := range aps { - t := &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cdTimeEnd} - timespans = append(timespans, aps.SplitInTimeSlots(t)) - } - return -} - func (c *ActivationPeriod) AddRatingProfile(rp ...*RatingProfile) { for _, r := range rp { c.RatingProfiles = append(c.RatingProfiles, r) @@ -40,23 +105,15 @@ func (c *Customer) AddActivationPeriod(ap ...*ActivationPeriod) { } } -func (c *Customer) SplitInTimeSpans(cd *CallDescription) (timespans []*TimeSpans) { - t := &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cdTimeEnd} - for i, ap := range c.ActivationPeriods { - timespans = append(timespans, aps.SplitInTimeSlots(t)) - } - return -} - func (c *Customer) CleanOldActivationPeriods() { - now := time.Now() + /*now := time.Now() obsoleteIndex := -1 for i, ap := range c.ActivationPeriods { if i > len(c.ActivationPeriods) - 2 { break } - if a - } + //if a + }*/ } diff --git a/timeslots/timeslots_test.go b/timeslots/timeslots_test.go index 4f71566de..611f66fcb 100644 --- a/timeslots/timeslots_test.go +++ b/timeslots/timeslots_test.go @@ -12,8 +12,8 @@ func setUp() { c1.AddActivationPeriod(ap1) d1,_ := time.ParseDuration("1m") d2,_ := time.ParseDuration("2m") - r1 := &RatingProfile{StartTime: d1, ConnectFee: 1.1, Price: 0.1, BillingUnit: SECOND} - r2 := &RatingProfile{StartTime: d2, ConnectFee: 2.2, Price: 0.2, BillingUnit: SECOND} + r1 := &RatingProfile{StartTime: d1, ConnectFee: 1.1, Price: 0.1, BillingUnit: 0.1} + r2 := &RatingProfile{StartTime: d2, ConnectFee: 2.2, Price: 0.2, BillingUnit: 0.1} ap1.AddRatingProfile(r1, r2) }