pull/5/merge
Icedream 2016-10-23 13:11:31 +00:00 committed by GitHub
commit 4c04df4b39
23 changed files with 436 additions and 78 deletions

View File

@ -4,7 +4,7 @@ go:
- 1.4.3
- 1.5.4
- 1.6.2
- release
- 1.7
- tip
install:

View File

@ -26,22 +26,20 @@ import (
)
func main() {
// Create client
client := footballdata.NewClient(http.DefaultClient)
// Tell it to use our API token
client.AuthToken = "<insert your api token here>"
// Create client (optionally with auth token)
client := new(footballdata.Client).
WithToken("<insert your api token here>")
// Get list of seasons...
seasons, err := client.SoccerSeasons().Do()
competitions, err := client.Competitions().Do()
if err != nil {
panic(err)
}
// ...and print them
for _, season := range seasons {
fmt.Println(season.Id, season.Caption)
for _, competition := range competitions {
fmt.Println(competition.Id, competition.Caption)
}
}
```
```

View File

@ -6,11 +6,11 @@ import (
)
type request struct {
c *Client
p string
v url.Values
fdClient *Client
path string
urlValues url.Values
}
func (r request) doJson(method string) (*json.Decoder, ResponseMeta, error) {
return r.c.doJson(method, r.p, r.v)
return r.fdClient.doJson(method, r.path, r.urlValues)
}

View File

@ -5,9 +5,12 @@ import "time"
type FixtureStatus string
const (
FixtureStatus_Timed FixtureStatus = "TIMED"
FixtureStatus_InPlay FixtureStatus = "IN_PLAY"
FixtureStatus_Finished FixtureStatus = "FINISHED"
FixtureStatus_Scheduled FixtureStatus = "SCHEDULED"
FixtureStatus_Timed FixtureStatus = "TIMED"
FixtureStatus_Postponed FixtureStatus = "POSTPONED"
FixtureStatus_InPlay FixtureStatus = "IN_PLAY"
FixtureStatus_Canceled FixtureStatus = "CANCELED"
FixtureStatus_Finished FixtureStatus = "FINISHED"
)
// Describes the venue.
@ -20,9 +23,13 @@ const (
Venue_Away Venue = "away"
)
// DEPRECATED.
//
// Contains the list of soccer seasons returned by the API.
type SoccerSeasonList []SoccerSeason
// DEPRECATED.
//
// Contains information about a soccer season.
type SoccerSeason struct {
Id uint64
@ -33,7 +40,23 @@ type SoccerSeason struct {
NumberOfMatchdays uint16
NumberOfTeams uint16
NumberOfGames uint16
LastUpdates time.Time
LastUpdated time.Time
}
// Contains the list of competitions returned by the API.
type CompetitionList []Competition
// Contains information about a competition.
type Competition struct {
Id uint64
Caption string
League string
Year string
CurrentMatchday uint16
NumberOfMatchdays uint16
NumberOfTeams uint16
NumberOfGames uint16
LastUpdated time.Time
}
// Contains the fixture and the head to head information delivered by the API
@ -130,3 +153,35 @@ type Player struct {
ContractUntil time.Time
MarketValue string
}
// Contains the league table for a season.
type LeagueTable struct {
LeagueCaption string
Matchday uint16
Standing []TeamLeagueStatistics
}
// Contains statistical information about a team's performance in a league.
type TeamLeagueStatistics struct {
CrestURI string
Draws uint16
GoalDifference int16
Goals uint16
GoalsAgainst uint16
Losses uint16
PlayedGames uint8
Points uint16
Position uint8
TeamName string
Wins uint16
Home ShortTeamLeagueStatistics
Away ShortTeamLeagueStatistics
}
type ShortTeamLeagueStatistics struct {
Draws uint16
Goals uint16
GoalsAgainst uint16
Losses uint16
Wins uint16
}

View File

@ -11,20 +11,63 @@ import (
)
/*
Provides a high-level client to talk to the API that football-data.org offers.
Provides a high-level client implementation to talk to the API that football-data.org offers.
To create an instance please use NewClient(h).
A new instance of Client will by default use the default HTTP client and no
authentication token. To configure this, Client provides methods to set the
token and the HTTP client. For more information, see the respective documentation
of SetHttpClient and SetToken, or take a look at the fluent-style companion
methods WithHttpClient and WithToken.
*/
type Client struct {
h *http.Client
httpClient http.Client
// Insert an API token here if you have one. It will be sent across with all requests.
AuthToken string
authToken string
}
// Creates a new Client instance that wraps around the given HTTP client.
// NewClient creates a new Client instance that wraps around the given HTTP client.
//
// A call to this method is not necessary in order to create a working instance
// of Client. `new(footballdata.Client)` works just as fine.
func NewClient(h *http.Client) *Client {
return &Client{h: h}
return &Client{httpClient: *h}
}
// SetToken sets the authentication token.
// Calling this method is *optional*.
func (c *Client) SetToken(authToken string) {
c.authToken = authToken
}
// WithToken sets the authentication token on a copy of the current Client
// instance.
//
// This method allows for easy fluent-style usage.
func (c Client) WithToken(authToken string) *Client {
c.authToken = authToken
return &c
}
// SetHttpClient sets the client that should be used to send out requests.
// Calling this method is *optional*.
func (c *Client) SetHttpClient(client *http.Client) {
if client == nil {
panic("client must not be nil")
}
c.httpClient = *client
}
// WithHttpClient sets the client that should be used to send out requests on
// a copy of the current Client instance.
//
// This method allows for easy fluent-style usage.
func (c Client) WithHttpClient(client *http.Client) *Client {
if client == nil {
panic("client must not be nil")
}
c.httpClient = *client
return &c
}
func (c *Client) req(path string, pathValues ...interface{}) request {
@ -41,14 +84,14 @@ func (c *Client) doJson(method string, path string, values url.Values) (j *json.
}
// Set request headers
if len(c.AuthToken) > 0 {
req.Header.Set("X-Auth-Token", c.AuthToken)
if len(c.authToken) > 0 {
req.Header.Set("X-Auth-Token", c.authToken)
}
req.Header.Set("X-Response-Control", "minified")
req.Header.Set("User-Agent", "go-footballdata/0.0")
req.Header.Set("User-Agent", "go-footballdata/0.1")
// Execute request
resp, err := c.h.Do(req)
resp, err := c.httpClient.Do(req)
if err != nil {
return
}

20
client_test.go Normal file
View File

@ -0,0 +1,20 @@
package footballdata
import (
"net/http"
"testing"
"github.com/stretchr/testify/require"
)
func Test_Client_New(t *testing.T) {
client := NewClient(http.DefaultClient)
_, err := client.Competitions().Do()
require.Nil(t, err)
}
func Test_Client_GoNew(t *testing.T) {
client := new(Client)
_, err := client.Competitions().Do()
require.Nil(t, err)
}

View File

@ -8,20 +8,64 @@ import (
)
func Example() {
// Create client
client := footballdata.NewClient(http.DefaultClient)
// Tell it to use our API token
client.AuthToken = "<insert your api token here>"
// Create client (optionally with auth token)
client := new(footballdata.Client).
WithToken("<insert your api token here>")
// Get list of seasons...
seasons, err := client.SoccerSeasons().Do()
competitions, err := client.Competitions().Do()
if err != nil {
panic(err)
}
// ...and print them
for _, season := range seasons {
fmt.Println(season.Id, season.Caption)
// ... and print them.
for _, competition := range competitions {
fmt.Println(competition.Id, competition.Caption)
}
}
func ExampleClient() {
// Create client (optionally with auth token)
client := new(footballdata.Client).
WithToken("<insert your api token here>")
// Tell it to use our API token (optional)
client.SetToken("<insert your api token here>")
// Do something with the client instance...
// Here we just fetch the listed soccer seasons on the API
competitions, err := client.Competitions().Do()
if err != nil {
panic(err)
}
for _, competition := range competitions {
fmt.Println(competition.Id, competition.Caption)
}
}
func ExampleClient_setTokenAndHttpClient() {
// Create client
client := new(footballdata.Client)
// If you have an API token, you can tell the Client instance to use it
client.SetToken("<insert your api token here>")
// The Client instance also allows you to use your own HTTP client configuration
client.SetHttpClient(&http.Client{
Transport: &http.Transport{
DisableCompression: true,
}})
}
func ExampleClient_withCustomConfiguration() {
// Create client with custom token and wrapping a custom HTTP client
client := new(footballdata.Client).
WithToken("<insert your api token here>").
WithHttpClient(&http.Client{
Transport: &http.Transport{
DisableCompression: true,
}})
// Do something with the client instance here...
_ = client
}

19
req_competition.go Normal file
View File

@ -0,0 +1,19 @@
package footballdata
type CompetitionRequest struct{ request }
// Do executes the request.
func (r CompetitionRequest) Do() (s Competition, err error) {
d, _, err := r.doJson("GET")
if err != nil {
return
}
err = d.Decode(&s)
return
}
// Competition prepares a request to fetch the complete list of soccer seasons.
func (c *Client) Competition(id uint64) CompetitionRequest {
return CompetitionRequest{c.req("competitions/%d", id)}
}

View File

@ -0,0 +1,52 @@
package footballdata
import (
"fmt"
"time"
)
type CompetitionFixturesRequest struct{ request }
// Matchday modifies the request to specify a match day.
func (r CompetitionFixturesRequest) Matchday(matchday uint16) CompetitionFixturesRequest {
r.urlValues.Set("matchday", fmt.Sprintf("%d", matchday))
return r
}
// TimeFrame modifies the request to specify a specific relative time frame.
func (r CompetitionFixturesRequest) TimeFrame(timeframe time.Duration) CompetitionFixturesRequest {
r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe))
return r
}
// TimeFrameStart modifies the request to specify the beginning of the time frame filter for the returned results.
//
// Only the year, month and day of the Time value will be used for the request.
func (r CompetitionFixturesRequest) TimeFrameStart(date time.Time) CompetitionFixturesRequest {
r.urlValues.Set("timeFrameStart", date.Format(timeFrameLayout))
return r
}
// TimeFrameEnd modifies the request to specify the end of the time frame filter for the returned results.
//
// Only the year, month and day of the Time value will be used for the request.
func (r CompetitionFixturesRequest) TimeFrameEnd(date time.Time) CompetitionFixturesRequest {
r.urlValues.Set("timeFrameEnd", date.Format(timeFrameLayout))
return r
}
// Do executes the request.
func (r CompetitionFixturesRequest) Do() (s FixtureList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
return
}
err = d.Decode(&s)
return
}
// FixturesOfCompetition prepares a request to fetch the fixtures of a soccer season.
func (c *Client) FixturesOfCompetition(soccerSeasonId uint64) CompetitionFixturesRequest {
return CompetitionFixturesRequest{c.req("competitions/%d/fixtures", soccerSeasonId)}
}

View File

@ -0,0 +1,27 @@
package footballdata
import "fmt"
type CompetitionLeagueTableRequest struct{ request }
// Matchday modifies the request to specify a match day.
func (r CompetitionLeagueTableRequest) Matchday(matchday uint16) CompetitionLeagueTableRequest {
r.urlValues.Set("matchday", fmt.Sprintf("%d", matchday))
return r
}
// Do executes the request.
func (r CompetitionLeagueTableRequest) Do() (s LeagueTable, err error) {
d, _, err := r.doJson("GET")
if err != nil {
return
}
err = d.Decode(&s)
return
}
// LeagueTableOfCompetition prepares a new request to fetch the league table of a given soccer season.
func (c *Client) LeagueTableOfCompetition(soccerSeasonId uint64) CompetitionLeagueTableRequest {
return CompetitionLeagueTableRequest{c.req("competitions/%d/leagueTable", soccerSeasonId)}
}

19
req_competition_teams.go Normal file
View File

@ -0,0 +1,19 @@
package footballdata
type CompetitionTeamsRequest struct{ request }
// Do executes the request.
func (r CompetitionTeamsRequest) Do() (s TeamList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
return
}
err = d.Decode(&s)
return
}
// TeamsOfCompetition prepares a new request to fetch the league table of a given soccer season.
func (c *Client) TeamsOfCompetition(soccerSeasonId uint64) CompetitionTeamsRequest {
return CompetitionTeamsRequest{c.req("competitions/%d/leagueTable", soccerSeasonId)}
}

27
req_competitions.go Normal file
View File

@ -0,0 +1,27 @@
package footballdata
import "fmt"
type CompetitionsRequest struct{ request }
// Season modifies the request to specify a season.
func (r CompetitionsRequest) Season(num uint32) CompetitionsRequest {
r.urlValues.Set("season", fmt.Sprintf("%d", num))
return r
}
// Do executes the request.
func (r CompetitionsRequest) Do() (s CompetitionList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
return
}
err = d.Decode(&s)
return
}
// Competitions prepares a request to fetch the list of competitions for the current season or for any specified season (via the "Season" submethod).
func (c *Client) Competitions() CompetitionsRequest {
return CompetitionsRequest{c.req("competitions")}
}

View File

@ -4,13 +4,13 @@ import "fmt"
type FixtureRequest struct{ request }
// Modifies the request to specify the number of former games to be analyzed (normally 10).
// Head2Head modifies the request to specify the number of former games to be analyzed (normally 10).
func (r FixtureRequest) Head2Head(num uint16) FixtureRequest {
r.v.Set("head2head", fmt.Sprintf("%d", num))
r.urlValues.Set("head2head", fmt.Sprintf("%d", num))
return r
}
// Executes the request.
// Do executes the request.
func (r FixtureRequest) Do() (s Fixture, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -21,7 +21,7 @@ func (r FixtureRequest) Do() (s Fixture, err error) {
return
}
// Prepares a request to fetch the fixtures of a soccer season.
// Fixture prepares a request to fetch the fixtures of a soccer season.
func (c *Client) Fixture(id uint64) FixtureRequest {
return FixtureRequest{c.req("fixture/%d", id)}
}

View File

@ -7,19 +7,35 @@ import (
type FixturesRequest struct{ request }
// Modifies the request to specify a specific time frame.
// TimeFrame modifies the request to specify a specific relative time frame.
func (r FixturesRequest) TimeFrame(timeframe time.Duration) FixturesRequest {
r.v.Set("timeFrame", durationToTimeFrame(timeframe))
r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe))
return r
}
// Modifies the request to specify a list of leagues by their code.
// TimeFrameStart modifies the request to specify the beginning of the time frame filter for the returned results.
//
// Only the year, month and day of the Time value will be used for the request.
func (r FixturesRequest) TimeFrameStart(date time.Time) FixturesRequest {
r.urlValues.Set("timeFrameStart", date.Format(timeFrameLayout))
return r
}
// TimeFrameEnd modifies the request to specify the end of the time frame filter for the returned results.
//
// Only the year, month and day of the Time value will be used for the request.
func (r FixturesRequest) TimeFrameEnd(date time.Time) FixturesRequest {
r.urlValues.Set("timeFrameEnd", date.Format(timeFrameLayout))
return r
}
// League modifies the request to specify a list of leagues by their code.
func (r FixturesRequest) League(leagueCodes ...string) FixturesRequest {
r.v.Set("league", strings.Join(leagueCodes, ","))
r.urlValues.Set("league", strings.Join(leagueCodes, ","))
return r
}
// Executes the request.
// Do executes the request.
func (r FixturesRequest) Do() (s FixturesResponse, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -30,7 +46,7 @@ func (r FixturesRequest) Do() (s FixturesResponse, err error) {
return
}
// Prepares a request to fetch the fixtures of a soccer season.
// Fixtures prepares a request to fetch the fixtures of a soccer season.
func (c *Client) Fixtures() FixturesRequest {
return FixturesRequest{c.req("fixtures")}
}

View File

@ -1,8 +1,12 @@
package footballdata
// DEPRECATED.
//
type SoccerSeasonRequest struct{ request }
// Executes the request.
// DEPRECATED.
//
// Do executes the request.
func (r SoccerSeasonRequest) Do() (s SoccerSeason, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -13,7 +17,9 @@ func (r SoccerSeasonRequest) Do() (s SoccerSeason, err error) {
return
}
// Prepares a request to fetch the complete list of soccer seasons.
// DEPRECATED.
//
// SoccerSeason prepares a request to fetch the complete list of soccer seasons.
func (c *Client) SoccerSeason(id uint64) SoccerSeasonRequest {
return SoccerSeasonRequest{c.req("soccerseasons/%d", id)}
}

View File

@ -5,21 +5,29 @@ import (
"time"
)
// DEPRECATED.
//
type SoccerSeasonFixturesRequest struct{ request }
// Modifies the request to specify a match day.
// DEPRECATED.
//
// Matchday modifies the request to specify a match day.
func (r SoccerSeasonFixturesRequest) Matchday(matchday uint16) SoccerSeasonFixturesRequest {
r.v.Set("matchday", fmt.Sprintf("%d", matchday))
r.urlValues.Set("matchday", fmt.Sprintf("%d", matchday))
return r
}
// Modifies the request to specify a specific time frame.
// DEPRECATED.
//
// TimeFrame modifies the request to specify a specific time frame.
func (r SoccerSeasonFixturesRequest) TimeFrame(timeframe time.Duration) SoccerSeasonFixturesRequest {
r.v.Set("timeFrame", durationToTimeFrame(timeframe))
r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe))
return r
}
// Executes the request.
// DEPRECATED.
//
// Do executes the request.
func (r SoccerSeasonFixturesRequest) Do() (s FixtureList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -30,7 +38,9 @@ func (r SoccerSeasonFixturesRequest) Do() (s FixtureList, err error) {
return
}
// Prepares a request to fetch the fixtures of a soccer season.
// DEPRECATED.
//
// FixturesOfSoccerSeason prepares a request to fetch the fixtures of a soccer season.
func (c *Client) FixturesOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonFixturesRequest {
return SoccerSeasonFixturesRequest{c.req("soccerseasons/%d/fixtures", soccerSeasonId)}
}

View File

@ -4,14 +4,18 @@ import "fmt"
type SoccerSeasonLeagueTableRequest struct{ request }
// Modifies the request to specify a match day.
// DEPRECATED.
//
// Matchday modifies the request to specify a match day.
func (r SoccerSeasonLeagueTableRequest) Matchday(matchday uint16) SoccerSeasonLeagueTableRequest {
r.v.Set("matchday", fmt.Sprintf("%d", matchday))
r.urlValues.Set("matchday", fmt.Sprintf("%d", matchday))
return r
}
// Executes the request.
func (r SoccerSeasonLeagueTableRequest) Do() (s SoccerSeason, err error) {
// DEPRECATED.
//
// Do executes the request.
func (r SoccerSeasonLeagueTableRequest) Do() (s LeagueTable, err error) {
d, _, err := r.doJson("GET")
if err != nil {
return
@ -21,7 +25,9 @@ func (r SoccerSeasonLeagueTableRequest) Do() (s SoccerSeason, err error) {
return
}
// Prepares a new request to fetch the league table of a given soccer season.
// DEPRECATED.
//
// LeagueTableOfSoccerSeason prepares a new request to fetch the league table of a given soccer season.
func (c *Client) LeagueTableOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonLeagueTableRequest {
return SoccerSeasonLeagueTableRequest{c.req("soccerseasons/%d/leagueTable", soccerSeasonId)}
}

View File

@ -1,8 +1,12 @@
package footballdata
// DEPRECATED.
//
type SoccerSeasonTeamsRequest struct{ request }
// Executes the request.
// DEPRECATED.
//
// Do executes the request.
func (r SoccerSeasonTeamsRequest) Do() (s TeamList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -13,7 +17,9 @@ func (r SoccerSeasonTeamsRequest) Do() (s TeamList, err error) {
return
}
// Prepares a new request to fetch the league table of a given soccer season.
// DEPRECATED.
//
// TeamsOfSoccerSeason prepares a new request to fetch the league table of a given soccer season.
func (c *Client) TeamsOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonTeamsRequest {
return SoccerSeasonTeamsRequest{c.req("soccerseasons/%d/leagueTable", soccerSeasonId)}
}

View File

@ -2,15 +2,21 @@ package footballdata
import "fmt"
// DEPRECATED.
//
type SoccerSeasonsRequest struct{ request }
// Modifies the request to specify a season.
// DEPRECATED.
//
// Season modifies the request to specify a season.
func (r SoccerSeasonsRequest) Season(num uint32) SoccerSeasonsRequest {
r.v.Set("season", fmt.Sprintf("%d", num))
r.urlValues.Set("season", fmt.Sprintf("%d", num))
return r
}
// Executes the request.
// DEPRECATED.
//
// Do executes the request.
func (r SoccerSeasonsRequest) Do() (s SoccerSeasonList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -21,7 +27,9 @@ func (r SoccerSeasonsRequest) Do() (s SoccerSeasonList, err error) {
return
}
// Prepares a request to fetch the complete list of soccer seasons.
// DEPRECATED.
//
// SoccerSeasons prepares a request to fetch the list of soccer seasons for the current season or for any specified season (via the "Season" submethod).
func (c *Client) SoccerSeasons() SoccerSeasonsRequest {
return SoccerSeasonsRequest{c.req("soccerseasons")}
}

View File

@ -5,7 +5,7 @@ type TeamRequest struct {
id uint64
}
// Executes the request.
// Do executes the request.
func (r TeamRequest) Do() (s Team, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -20,7 +20,7 @@ func (r TeamRequest) Do() (s Team, err error) {
return
}
// Prepares a request to fetch a team's information.
// Team prepares a request to fetch a team's information.
func (c *Client) Team(id uint64) TeamRequest {
return TeamRequest{c.req("teams/%d", id), id}
}

View File

@ -7,25 +7,25 @@ import (
type TeamFixturesRequest struct{ request }
// Modifies the request to specify a specific time frame.
// TimeFrame modifies the request to specify a specific time frame.
func (r TeamFixturesRequest) TimeFrame(timeframe time.Duration) TeamFixturesRequest {
r.v.Set("timeFrame", durationToTimeFrame(timeframe))
r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe))
return r
}
// Modifies the request to specify a list of leagues by their code.
// Season modifies the request to specify a list of leagues by their code.
func (r TeamFixturesRequest) Season(season uint64) TeamFixturesRequest {
r.v.Set("season", fmt.Sprintf("%d", season))
r.urlValues.Set("season", fmt.Sprintf("%d", season))
return r
}
// Modifies the request to specify a venue.
// Venue modifies the request to specify a venue.
func (r TeamFixturesRequest) Venue(venue Venue) TeamFixturesRequest {
r.v.Set("venue", string(venue))
r.urlValues.Set("venue", string(venue))
return r
}
// Executes the request.
// Do executes the request.
func (r TeamFixturesRequest) Do() (s FixturesResponse, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -36,7 +36,7 @@ func (r TeamFixturesRequest) Do() (s FixturesResponse, err error) {
return
}
// Prepares a request to fetch the fixtures of a soccer season.
// FixturesOfTeam prepares a request to fetch the fixtures of a soccer season.
func (c *Client) FixturesOfTeam(id uint64) TeamFixturesRequest {
return TeamFixturesRequest{c.req("teams/%d/fixtures", id)}
}

View File

@ -2,7 +2,7 @@ package footballdata
type TeamPlayersRequest struct{ request }
// Executes the request.
// Do executes the request.
func (r TeamPlayersRequest) Do() (s PlayerList, err error) {
d, _, err := r.doJson("GET")
if err != nil {
@ -13,7 +13,7 @@ func (r TeamPlayersRequest) Do() (s PlayerList, err error) {
return
}
// Prepares a request to fetch a team's players.
// PlayersOfTeam prepares a request to fetch a team's players.
func (c *Client) PlayersOfTeam(id uint64) TeamPlayersRequest {
return TeamPlayersRequest{c.req("teams/%d/players", id)}
}

View File

@ -8,6 +8,8 @@ import (
const (
day = 24 * time.Hour
week = 7 * day
timeFrameLayout = "2006-01-02"
)
func durationToTimeFrame(d time.Duration) (r string) {