Skip to content

Commit

Permalink
Refactor duration
Browse files Browse the repository at this point in the history
  • Loading branch information
francesconi committed Jan 22, 2025
1 parent 31ecd42 commit f0cfb96
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 56 deletions.
47 changes: 47 additions & 0 deletions duration/duration_days.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package duration

import (
"fmt"
"regexp"
"strconv"
)

type Days int

var regexpDays = regexp.MustCompile(`^P(P<days>[0-9]+)D$`)

func ParseDays(s string) (Days, error) {
var d Days

if !regexpDays.MatchString(s) {
return d, fmt.Errorf("invalid duration format: %s, expected format is 'PxD'", s)
}

matches := regexpDays.FindStringSubmatch(s)
for i, name := range regexpDays.SubexpNames() {
switch match := matches[i]; name {
case "days":
days, err := strconv.Atoi(match)
if err != nil {
return d, err
}
d = Days(days)
}
}

return d, nil
}

func (d Days) String() string {
return fmt.Sprintf("P%dD", d)
}

func (d Days) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}

func (d *Days) UnmarshalText(data []byte) error {
var err error
*d, err = ParseDays(string(data))
return err
}
47 changes: 47 additions & 0 deletions duration/duration_nights.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package duration

import (
"fmt"
"regexp"
"strconv"
)

type Nights int

var regexpNights = regexp.MustCompile(`^P(P<nights>[0-9]+)N$`)

func ParseNights(s string) (Nights, error) {
var d Nights

if !regexpNights.MatchString(s) {
return d, fmt.Errorf("invalid duration format: %s, expected format is 'PxN'", s)
}

matches := regexpNights.FindStringSubmatch(s)
for i, name := range regexpNights.SubexpNames() {
switch match := matches[i]; name {
case "nights":
nights, err := strconv.Atoi(match)
if err != nil {
return d, err
}
d = Nights(nights)
}
}

return d, nil
}

func (d Nights) String() string {
return fmt.Sprintf("P%dN", d)
}

func (d Nights) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}

func (d *Nights) UnmarshalText(data []byte) error {
var err error
*d, err = ParseNights(string(data))
return err
}
7 changes: 6 additions & 1 deletion v_2018_10/types_hotel_descriptive_content_notif.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,9 @@ type URL struct {
Value string `xml:",innerxml"`
}

type VideoFormat ImageFormat
type HotelDescriptiveContentNotifRS struct {
response

XMLName xml.Name `xml:"http://www.opentravel.org/OTA/2003/05 OTA_HotelDescriptiveContentNotifRS"`
Version string `xml:"Version,attr"`
}
55 changes: 2 additions & 53 deletions v_2018_10/types_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package v_2018_10

import (
"encoding/xml"
"fmt"
"regexp"
"strconv"
"time"

"github.com/HGV/alpinebits/duration"
"github.com/HGV/x/timex"
)

Expand Down Expand Up @@ -96,13 +94,6 @@ type CommissionPayableAmount struct {
CurrencyCode string `xml:"CurrencyCode,attr"`
}

type MealsIncluded struct {
MealPlanIndicator bool `xml:"MealPlanIndicator,attr"`
// MealPlanCodes BoardType `xml:"MealPlanCodes,attr"`
}

// TODO: BoardType

type GuestCount struct {
Count int `xml:"Count,attr"`
Age *int `xml:"Age,attr"`
Expand All @@ -111,52 +102,10 @@ type GuestCount struct {
type TimeSpan struct {
Start *timex.Date `xml:"Start,attr"`
End *timex.Date `xml:"End,attr"`
Duration *Duration `xml:"Duration,attr"`
Duration *duration.Nights `xml:"Duration,attr"`
StartDateWindow *StartDateWindow `xml:"StartDateWindow"`
}

type Duration struct {
Nights int
}

var regexpDuration = regexp.MustCompile(`^P(P<nights>[0-9]+)N$`)

func ParseDuration(s string) (Duration, error) {
var d Duration

if !regexpDuration.MatchString(s) {
return d, fmt.Errorf("invalid duration format: %s, expected format is 'PxN'", s)
}

matches := regexpDuration.FindStringSubmatch(s)
for i, name := range regexpDuration.SubexpNames() {
switch match := matches[i]; name {
case "nights":
nights, err := strconv.Atoi(match)
if err != nil {
return d, err
}
d.Nights = nights
}
}

return d, nil
}

func (d *Duration) UnmarshalText(data []byte) error {
var err error
*d, err = ParseDuration(string(data))
return err
}

func (d Duration) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}

func (d Duration) String() string {
return fmt.Sprintf("P%dN", d.Nights)
}

type StartDateWindow struct {
EarliestDate timex.Date `xml:"EarliestDate,attr"`
LatestDate timex.Date `xml:"LatestDate,attr"`
Expand Down
6 changes: 4 additions & 2 deletions v_2018_10/validation_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package v_2018_10
import (
"net/mail"
"strings"

"github.com/HGV/alpinebits/duration"
)

type ReadValidator struct{}
Expand Down Expand Up @@ -215,7 +217,7 @@ func (v ResRetrieveValidator) validateTimeSpan(timeSpan TimeSpan) error {
return nil
}

func (v ResRetrieveValidator) validateStartDateWindow(w *StartDateWindow, d Duration) error {
func (v ResRetrieveValidator) validateStartDateWindow(w *StartDateWindow, nights duration.Nights) error {
if w == nil {
return ErrMissingStartDateWindow
}
Expand All @@ -224,7 +226,7 @@ func (v ResRetrieveValidator) validateStartDateWindow(w *StartDateWindow, d Dura
return ErrEarliestDateAfterLatestDate
}

if d.Nights <= w.LatestDate.DaysSince(w.EarliestDate) {
if int(nights) <= w.LatestDate.DaysSince(w.EarliestDate) {
return ErrDurationOutOfRange
}

Expand Down

0 comments on commit f0cfb96

Please sign in to comment.