mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
Public holidays API (#212)
This commit is contained in:
69
clients/go/holidays/holidays.go
Executable file
69
clients/go/holidays/holidays.go
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
package holidays
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/m3o/m3o-go/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewHolidaysService(token string) *HolidaysService {
|
||||||
|
return &HolidaysService{
|
||||||
|
client: client.NewClient(&client.Options{
|
||||||
|
Token: token,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HolidaysService struct {
|
||||||
|
client *client.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (t *HolidaysService) Countries(request *CountriesRequest) (*CountriesResponse, error) {
|
||||||
|
rsp := &CountriesResponse{}
|
||||||
|
return rsp, t.client.Call("holidays", "Countries", request, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (t *HolidaysService) List(request *ListRequest) (*ListResponse, error) {
|
||||||
|
rsp := &ListResponse{}
|
||||||
|
return rsp, t.client.Call("holidays", "List", request, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CountriesRequest struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type CountriesResponse struct {
|
||||||
|
Countries []Country `json:"countries"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Country struct {
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
Code string `json:"code"`
|
||||||
|
// The English name of the country
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Holiday struct {
|
||||||
|
// the country this holiday occurs in
|
||||||
|
CountryCode string `json:"countryCode"`
|
||||||
|
// date of the holiday in yyyy-mm-dd format
|
||||||
|
Date string `json:"date"`
|
||||||
|
// the local name of the holiday
|
||||||
|
LocalName string `json:"localName"`
|
||||||
|
// the name of the holiday in English
|
||||||
|
Name string `json:"name"`
|
||||||
|
// the regions within the country that observe this holiday (if not all of them)
|
||||||
|
Regions []string `json:"regions"`
|
||||||
|
// the type of holiday Public, Bank, School, Authorities, Optional, Observance
|
||||||
|
Types []string `json:"types"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListRequest struct {
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
CountryCode string `json:"countryCode"`
|
||||||
|
// The year to list holidays for
|
||||||
|
Year int64 `json:"year"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResponse struct {
|
||||||
|
Holidays []Holiday `json:"holidays"`
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/micro/services/clients/go/forex"
|
"github.com/micro/services/clients/go/forex"
|
||||||
"github.com/micro/services/clients/go/geocoding"
|
"github.com/micro/services/clients/go/geocoding"
|
||||||
"github.com/micro/services/clients/go/helloworld"
|
"github.com/micro/services/clients/go/helloworld"
|
||||||
|
"github.com/micro/services/clients/go/holidays"
|
||||||
"github.com/micro/services/clients/go/id"
|
"github.com/micro/services/clients/go/id"
|
||||||
"github.com/micro/services/clients/go/image"
|
"github.com/micro/services/clients/go/image"
|
||||||
"github.com/micro/services/clients/go/ip"
|
"github.com/micro/services/clients/go/ip"
|
||||||
@@ -52,6 +53,7 @@ func NewClient(token string) *Client {
|
|||||||
ForexService: forex.NewForexService(token),
|
ForexService: forex.NewForexService(token),
|
||||||
GeocodingService: geocoding.NewGeocodingService(token),
|
GeocodingService: geocoding.NewGeocodingService(token),
|
||||||
HelloworldService: helloworld.NewHelloworldService(token),
|
HelloworldService: helloworld.NewHelloworldService(token),
|
||||||
|
HolidaysService: holidays.NewHolidaysService(token),
|
||||||
IdService: id.NewIdService(token),
|
IdService: id.NewIdService(token),
|
||||||
ImageService: image.NewImageService(token),
|
ImageService: image.NewImageService(token),
|
||||||
IpService: ip.NewIpService(token),
|
IpService: ip.NewIpService(token),
|
||||||
@@ -91,6 +93,7 @@ type Client struct {
|
|||||||
ForexService *forex.ForexService
|
ForexService *forex.ForexService
|
||||||
GeocodingService *geocoding.GeocodingService
|
GeocodingService *geocoding.GeocodingService
|
||||||
HelloworldService *helloworld.HelloworldService
|
HelloworldService *helloworld.HelloworldService
|
||||||
|
HolidaysService *holidays.HolidaysService
|
||||||
IdService *id.IdService
|
IdService *id.IdService
|
||||||
ImageService *image.ImageService
|
ImageService *image.ImageService
|
||||||
IpService *ip.IpService
|
IpService *ip.IpService
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ type Result struct {
|
|||||||
// The associated arabic text
|
// The associated arabic text
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
// The related translations to the text
|
// The related translations to the text
|
||||||
Translations []Translation `json:"translations"`
|
Translations []Interpretation `json:"translations"`
|
||||||
// The unique verse id across the Quran
|
// The unique verse id across the Quran
|
||||||
VerseId int32 `json:"verseId"`
|
VerseId int32 `json:"verseId"`
|
||||||
// The verse key e.g 1:1
|
// The verse key e.g 1:1
|
||||||
@@ -161,7 +161,7 @@ type Verse struct {
|
|||||||
// The basic translation of the verse
|
// The basic translation of the verse
|
||||||
TranslatedText string `json:"translatedText"`
|
TranslatedText string `json:"translatedText"`
|
||||||
// The alternative translations for the verse
|
// The alternative translations for the verse
|
||||||
Translations []Translation `json:"translations"`
|
Translations []Interpretation `json:"translations"`
|
||||||
// The phonetic transliteration from arabic
|
// The phonetic transliteration from arabic
|
||||||
Transliteration string `json:"transliteration"`
|
Transliteration string `json:"transliteration"`
|
||||||
// The individual words within the verse (Ayah)
|
// The individual words within the verse (Ayah)
|
||||||
|
|||||||
64
clients/ts/holidays/index.ts
Executable file
64
clients/ts/holidays/index.ts
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
import * as m3o from "@m3o/m3o-node";
|
||||||
|
|
||||||
|
export class HolidaysService {
|
||||||
|
private client: m3o.Client;
|
||||||
|
|
||||||
|
constructor(token: string) {
|
||||||
|
this.client = new m3o.Client({ token: token });
|
||||||
|
}
|
||||||
|
//
|
||||||
|
countries(request: CountriesRequest): Promise<CountriesResponse> {
|
||||||
|
return this.client.call(
|
||||||
|
"holidays",
|
||||||
|
"Countries",
|
||||||
|
request
|
||||||
|
) as Promise<CountriesResponse>;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
list(request: ListRequest): Promise<ListResponse> {
|
||||||
|
return this.client.call(
|
||||||
|
"holidays",
|
||||||
|
"List",
|
||||||
|
request
|
||||||
|
) as Promise<ListResponse>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CountriesRequest {}
|
||||||
|
|
||||||
|
export interface CountriesResponse {
|
||||||
|
countries?: Country[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Country {
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
code?: string;
|
||||||
|
// The English name of the country
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Holiday {
|
||||||
|
// the country this holiday occurs in
|
||||||
|
countryCode?: string;
|
||||||
|
// date of the holiday in yyyy-mm-dd format
|
||||||
|
date?: string;
|
||||||
|
// the local name of the holiday
|
||||||
|
localName?: string;
|
||||||
|
// the name of the holiday in English
|
||||||
|
name?: string;
|
||||||
|
// the regions within the country that observe this holiday (if not all of them)
|
||||||
|
regions?: string[];
|
||||||
|
// the type of holiday Public, Bank, School, Authorities, Optional, Observance
|
||||||
|
types?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListRequest {
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
countryCode?: string;
|
||||||
|
// The year to list holidays for
|
||||||
|
year?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListResponse {
|
||||||
|
holidays?: Holiday[];
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import * as file from "./file";
|
|||||||
import * as forex from "./forex";
|
import * as forex from "./forex";
|
||||||
import * as geocoding from "./geocoding";
|
import * as geocoding from "./geocoding";
|
||||||
import * as helloworld from "./helloworld";
|
import * as helloworld from "./helloworld";
|
||||||
|
import * as holidays from "./holidays";
|
||||||
import * as id from "./id";
|
import * as id from "./id";
|
||||||
import * as image from "./image";
|
import * as image from "./image";
|
||||||
import * as ip from "./ip";
|
import * as ip from "./ip";
|
||||||
@@ -46,6 +47,7 @@ export class Client {
|
|||||||
this.forexService = new forex.ForexService(token);
|
this.forexService = new forex.ForexService(token);
|
||||||
this.geocodingService = new geocoding.GeocodingService(token);
|
this.geocodingService = new geocoding.GeocodingService(token);
|
||||||
this.helloworldService = new helloworld.HelloworldService(token);
|
this.helloworldService = new helloworld.HelloworldService(token);
|
||||||
|
this.holidaysService = new holidays.HolidaysService(token);
|
||||||
this.idService = new id.IdService(token);
|
this.idService = new id.IdService(token);
|
||||||
this.imageService = new image.ImageService(token);
|
this.imageService = new image.ImageService(token);
|
||||||
this.ipService = new ip.IpService(token);
|
this.ipService = new ip.IpService(token);
|
||||||
@@ -81,6 +83,7 @@ export class Client {
|
|||||||
forexService: forex.ForexService;
|
forexService: forex.ForexService;
|
||||||
geocodingService: geocoding.GeocodingService;
|
geocodingService: geocoding.GeocodingService;
|
||||||
helloworldService: helloworld.HelloworldService;
|
helloworldService: helloworld.HelloworldService;
|
||||||
|
holidaysService: holidays.HolidaysService;
|
||||||
idService: id.IdService;
|
idService: id.IdService;
|
||||||
imageService: image.ImageService;
|
imageService: image.ImageService;
|
||||||
ipService: ip.IpService;
|
ipService: ip.IpService;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"./forex": "./dist/forex/index.js",
|
"./forex": "./dist/forex/index.js",
|
||||||
"./geocoding": "./dist/geocoding/index.js",
|
"./geocoding": "./dist/geocoding/index.js",
|
||||||
"./helloworld": "./dist/helloworld/index.js",
|
"./helloworld": "./dist/helloworld/index.js",
|
||||||
|
"./holidays": "./dist/holidays/index.js",
|
||||||
"./id": "./dist/id/index.js",
|
"./id": "./dist/id/index.js",
|
||||||
"./image": "./dist/image/index.js",
|
"./image": "./dist/image/index.js",
|
||||||
"./ip": "./dist/ip/index.js",
|
"./ip": "./dist/ip/index.js",
|
||||||
@@ -59,5 +60,5 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"version": "1.0.521"
|
"version": "1.0.522"
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ export interface Result {
|
|||||||
// The associated arabic text
|
// The associated arabic text
|
||||||
text?: string;
|
text?: string;
|
||||||
// The related translations to the text
|
// The related translations to the text
|
||||||
translations?: Translation[];
|
translations?: Interpretation[];
|
||||||
// The unique verse id across the Quran
|
// The unique verse id across the Quran
|
||||||
verseId?: number;
|
verseId?: number;
|
||||||
// The verse key e.g 1:1
|
// The verse key e.g 1:1
|
||||||
@@ -149,7 +149,7 @@ export interface Verse {
|
|||||||
// The unique id of the verse in the whole book
|
// The unique id of the verse in the whole book
|
||||||
id?: number;
|
id?: number;
|
||||||
// The interpretations of the verse
|
// The interpretations of the verse
|
||||||
interpretations?: Translation[];
|
interpretations?: Interpretation[];
|
||||||
// The key of this verse (chapter:verse) e.g 1:1
|
// The key of this verse (chapter:verse) e.g 1:1
|
||||||
key?: string;
|
key?: string;
|
||||||
// The verse number in this chapter
|
// The verse number in this chapter
|
||||||
@@ -161,7 +161,7 @@ export interface Verse {
|
|||||||
// The basic translation of the verse
|
// The basic translation of the verse
|
||||||
translatedText?: string;
|
translatedText?: string;
|
||||||
// The alternative translations for the verse
|
// The alternative translations for the verse
|
||||||
translations?: Translation[];
|
translations?: Interpretation[];
|
||||||
// The phonetic transliteration from arabic
|
// The phonetic transliteration from arabic
|
||||||
transliteration?: string;
|
transliteration?: string;
|
||||||
// The individual words within the verse (Ayah)
|
// The individual words within the verse (Ayah)
|
||||||
|
|||||||
4
examples/holidays/countries/curl/listCountries.sh
Executable file
4
examples/holidays/countries/curl/listCountries.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
curl "https://api.m3o.com/v1/holidays/Countries" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $MICRO_API_TOKEN" \
|
||||||
|
-d '{}'
|
||||||
14
examples/holidays/countries/go/listCountries.go
Executable file
14
examples/holidays/countries/go/listCountries.go
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
package example
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/micro/services/clients/go/holidays"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
func ListCountries() {
|
||||||
|
holidaysService := holidays.NewHolidaysService(os.Getenv("MICRO_API_TOKEN"))
|
||||||
|
rsp, err := holidaysService.Countries(&holidays.CountriesRequest{})
|
||||||
|
fmt.Println(rsp, err)
|
||||||
|
}
|
||||||
12
examples/holidays/countries/node/listCountries.js
Executable file
12
examples/holidays/countries/node/listCountries.js
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
import * as holidays from "m3o/holidays";
|
||||||
|
|
||||||
|
//
|
||||||
|
async function ListCountries() {
|
||||||
|
let holidaysService = new holidays.HolidaysService(
|
||||||
|
process.env.MICRO_API_TOKEN
|
||||||
|
);
|
||||||
|
let rsp = await holidaysService.countries({});
|
||||||
|
console.log(rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
await ListCountries();
|
||||||
7
examples/holidays/list/curl/getHolidays.sh
Executable file
7
examples/holidays/list/curl/getHolidays.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
curl "https://api.m3o.com/v1/holidays/List" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $MICRO_API_TOKEN" \
|
||||||
|
-d '{
|
||||||
|
"country_code": "GB",
|
||||||
|
"year": 2022
|
||||||
|
}'
|
||||||
16
examples/holidays/list/go/getHolidays.go
Executable file
16
examples/holidays/list/go/getHolidays.go
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
package example
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/micro/services/clients/go/holidays"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
func GetHolidays() {
|
||||||
|
holidaysService := holidays.NewHolidaysService(os.Getenv("MICRO_API_TOKEN"))
|
||||||
|
rsp, err := holidaysService.List(&holidays.ListRequest{
|
||||||
|
Year: 2022,
|
||||||
|
})
|
||||||
|
fmt.Println(rsp, err)
|
||||||
|
}
|
||||||
15
examples/holidays/list/node/getHolidays.js
Executable file
15
examples/holidays/list/node/getHolidays.js
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
import * as holidays from "m3o/holidays";
|
||||||
|
|
||||||
|
//
|
||||||
|
async function GetHolidays() {
|
||||||
|
let holidaysService = new holidays.HolidaysService(
|
||||||
|
process.env.MICRO_API_TOKEN
|
||||||
|
);
|
||||||
|
let rsp = await holidaysService.list({
|
||||||
|
country_code: "GB",
|
||||||
|
year: 2022,
|
||||||
|
});
|
||||||
|
console.log(rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
await GetHolidays();
|
||||||
@@ -11,9 +11,9 @@ func PublishAmessage() {
|
|||||||
streamService := stream.NewStreamService(os.Getenv("MICRO_API_TOKEN"))
|
streamService := stream.NewStreamService(os.Getenv("MICRO_API_TOKEN"))
|
||||||
rsp, err := streamService.Publish(&stream.PublishRequest{
|
rsp, err := streamService.Publish(&stream.PublishRequest{
|
||||||
Message: map[string]interface{}{
|
Message: map[string]interface{}{
|
||||||
|
"type": "signup",
|
||||||
"user": "john",
|
"user": "john",
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"type": "signup",
|
|
||||||
},
|
},
|
||||||
Topic: "events",
|
Topic: "events",
|
||||||
})
|
})
|
||||||
|
|||||||
1
go.sum
1
go.sum
@@ -693,6 +693,7 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
|
|||||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
|||||||
2
holidays/.gitignore
vendored
Normal file
2
holidays/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
holidays
|
||||||
3
holidays/Dockerfile
Normal file
3
holidays/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
FROM alpine
|
||||||
|
ADD holidays /holidays
|
||||||
|
ENTRYPOINT [ "/holidays" ]
|
||||||
28
holidays/Makefile
Normal file
28
holidays/Makefile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
GOPATH:=$(shell go env GOPATH)
|
||||||
|
.PHONY: init
|
||||||
|
init:
|
||||||
|
go get -u github.com/golang/protobuf/proto
|
||||||
|
go get -u github.com/golang/protobuf/protoc-gen-go
|
||||||
|
go get github.com/micro/micro/v3/cmd/protoc-gen-micro
|
||||||
|
go get github.com/micro/micro/v3/cmd/protoc-gen-openapi
|
||||||
|
|
||||||
|
.PHONY: api
|
||||||
|
api:
|
||||||
|
protoc --openapi_out=. --proto_path=. proto/holidays.proto
|
||||||
|
|
||||||
|
.PHONY: proto
|
||||||
|
proto:
|
||||||
|
protoc --proto_path=. --micro_out=. --go_out=:. proto/holidays.proto
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
go build -o holidays *.go
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -v ./... -cover
|
||||||
|
|
||||||
|
.PHONY: docker
|
||||||
|
docker:
|
||||||
|
docker build . -t holidays:latest
|
||||||
15
holidays/README.md
Normal file
15
holidays/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Find the holidays observed in a particular country
|
||||||
|
|
||||||
|
# Holidays Service
|
||||||
|
|
||||||
|
List holidays observed in a country. Holidays may be at the country or region level.
|
||||||
|
|
||||||
|
Holiday types are:
|
||||||
|
- Public - public holiday
|
||||||
|
- Bank - banks and offices are closed
|
||||||
|
- School - schools are closed
|
||||||
|
- Authorities - Government or other authorities are closed
|
||||||
|
- Optional - A day where a majority of people take the day off
|
||||||
|
- Observance - Optional day off, typically unpaid
|
||||||
|
|
||||||
|
Powered by [Nager.Date](https://github.com/nager/Nager.Date/)
|
||||||
647
holidays/examples.json
Normal file
647
holidays/examples.json
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
{
|
||||||
|
"countries": [{
|
||||||
|
"title": "List countries",
|
||||||
|
"run_check": true,
|
||||||
|
"request": {},
|
||||||
|
"response": {
|
||||||
|
"countries": [
|
||||||
|
{
|
||||||
|
"code": "AD",
|
||||||
|
"name": "Andorra"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AL",
|
||||||
|
"name": "Albania"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AR",
|
||||||
|
"name": "Argentina"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AT",
|
||||||
|
"name": "Austria"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AU",
|
||||||
|
"name": "Australia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AX",
|
||||||
|
"name": "Åland Islands"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BA",
|
||||||
|
"name": "Bosnia and Herzegovina"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BB",
|
||||||
|
"name": "Barbados"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BE",
|
||||||
|
"name": "Belgium"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BG",
|
||||||
|
"name": "Bulgaria"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BJ",
|
||||||
|
"name": "Benin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BO",
|
||||||
|
"name": "Bolivia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BR",
|
||||||
|
"name": "Brazil"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BS",
|
||||||
|
"name": "Bahamas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BW",
|
||||||
|
"name": "Botswana"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BY",
|
||||||
|
"name": "Belarus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BZ",
|
||||||
|
"name": "Belize"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CA",
|
||||||
|
"name": "Canada"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CH",
|
||||||
|
"name": "Switzerland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CL",
|
||||||
|
"name": "Chile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CN",
|
||||||
|
"name": "China"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CO",
|
||||||
|
"name": "Colombia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CR",
|
||||||
|
"name": "Costa Rica"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CU",
|
||||||
|
"name": "Cuba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CY",
|
||||||
|
"name": "Cyprus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CZ",
|
||||||
|
"name": "Czechia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "DE",
|
||||||
|
"name": "Germany"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "DK",
|
||||||
|
"name": "Denmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "DO",
|
||||||
|
"name": "Dominican Republic"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "EC",
|
||||||
|
"name": "Ecuador"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "EE",
|
||||||
|
"name": "Estonia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "EG",
|
||||||
|
"name": "Egypt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ES",
|
||||||
|
"name": "Spain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FI",
|
||||||
|
"name": "Finland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FO",
|
||||||
|
"name": "Faroe Islands"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FR",
|
||||||
|
"name": "France"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GA",
|
||||||
|
"name": "Gabon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GB",
|
||||||
|
"name": "United Kingdom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GD",
|
||||||
|
"name": "Grenada"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GG",
|
||||||
|
"name": "Guernsey"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GI",
|
||||||
|
"name": "Gibraltar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GL",
|
||||||
|
"name": "Greenland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GM",
|
||||||
|
"name": "Gambia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GR",
|
||||||
|
"name": "Greece"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GT",
|
||||||
|
"name": "Guatemala"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GY",
|
||||||
|
"name": "Guyana"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "HN",
|
||||||
|
"name": "Honduras"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "HR",
|
||||||
|
"name": "Croatia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "HT",
|
||||||
|
"name": "Haiti"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "HU",
|
||||||
|
"name": "Hungary"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ID",
|
||||||
|
"name": "Indonesia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "IE",
|
||||||
|
"name": "Ireland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "IM",
|
||||||
|
"name": "Isle of Man"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "IS",
|
||||||
|
"name": "Iceland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "IT",
|
||||||
|
"name": "Italy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "JE",
|
||||||
|
"name": "Jersey"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "JM",
|
||||||
|
"name": "Jamaica"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "JP",
|
||||||
|
"name": "Japan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "KR",
|
||||||
|
"name": "South Korea"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LI",
|
||||||
|
"name": "Liechtenstein"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LS",
|
||||||
|
"name": "Lesotho"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LT",
|
||||||
|
"name": "Lithuania"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LU",
|
||||||
|
"name": "Luxembourg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LV",
|
||||||
|
"name": "Latvia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MA",
|
||||||
|
"name": "Morocco"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MC",
|
||||||
|
"name": "Monaco"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MD",
|
||||||
|
"name": "Moldova"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ME",
|
||||||
|
"name": "Montenegro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MG",
|
||||||
|
"name": "Madagascar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MK",
|
||||||
|
"name": "North Macedonia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MN",
|
||||||
|
"name": "Mongolia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MS",
|
||||||
|
"name": "Montserrat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MT",
|
||||||
|
"name": "Malta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MX",
|
||||||
|
"name": "Mexico"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MZ",
|
||||||
|
"name": "Mozambique"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NA",
|
||||||
|
"name": "Namibia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NE",
|
||||||
|
"name": "Niger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NG",
|
||||||
|
"name": "Nigeria"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NI",
|
||||||
|
"name": "Nicaragua"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NL",
|
||||||
|
"name": "Netherlands"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NO",
|
||||||
|
"name": "Norway"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NZ",
|
||||||
|
"name": "New Zealand"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PA",
|
||||||
|
"name": "Panama"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PE",
|
||||||
|
"name": "Peru"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PG",
|
||||||
|
"name": "Papua New Guinea"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PL",
|
||||||
|
"name": "Poland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PR",
|
||||||
|
"name": "Puerto Rico"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PT",
|
||||||
|
"name": "Portugal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PY",
|
||||||
|
"name": "Paraguay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RO",
|
||||||
|
"name": "Romania"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RS",
|
||||||
|
"name": "Serbia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RU",
|
||||||
|
"name": "Russia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SE",
|
||||||
|
"name": "Sweden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SG",
|
||||||
|
"name": "Singapore"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SI",
|
||||||
|
"name": "Slovenia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SJ",
|
||||||
|
"name": "Svalbard and Jan Mayen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SK",
|
||||||
|
"name": "Slovakia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SM",
|
||||||
|
"name": "San Marino"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SR",
|
||||||
|
"name": "Suriname"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SV",
|
||||||
|
"name": "El Salvador"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TN",
|
||||||
|
"name": "Tunisia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TR",
|
||||||
|
"name": "Turkey"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "UA",
|
||||||
|
"name": "Ukraine"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "US",
|
||||||
|
"name": "United States"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "UY",
|
||||||
|
"name": "Uruguay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VA",
|
||||||
|
"name": "Vatican City"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VE",
|
||||||
|
"name": "Venezuela"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VN",
|
||||||
|
"name": "Vietnam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ZA",
|
||||||
|
"name": "South Africa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ZW",
|
||||||
|
"name": "Zimbabwe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"title": "Get holidays",
|
||||||
|
"run_check": true,
|
||||||
|
"request": {"country_code": "GB", "year": 2022},
|
||||||
|
"response": {
|
||||||
|
"holidays": [
|
||||||
|
{
|
||||||
|
"date": "2022-01-01",
|
||||||
|
"name": "New Year's Day",
|
||||||
|
"local_name": "New Year's Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-NIR"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-01-03",
|
||||||
|
"name": "New Year's Day",
|
||||||
|
"local_name": "New Year's Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-ENG",
|
||||||
|
"GB-WLS"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-01-03",
|
||||||
|
"name": "New Year's Day",
|
||||||
|
"local_name": "New Year's Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-SCT"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-01-04",
|
||||||
|
"name": "New Year's Day",
|
||||||
|
"local_name": "New Year's Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-SCT"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-03-17",
|
||||||
|
"name": "Saint Patrick's Day",
|
||||||
|
"local_name": "Saint Patrick's Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-NIR"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-04-15",
|
||||||
|
"name": "Good Friday",
|
||||||
|
"local_name": "Good Friday",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-04-18",
|
||||||
|
"name": "Easter Monday",
|
||||||
|
"local_name": "Easter Monday",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-ENG",
|
||||||
|
"GB-WLS",
|
||||||
|
"GB-NIR"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-05-02",
|
||||||
|
"name": "Early May Bank Holiday",
|
||||||
|
"local_name": "Early May Bank Holiday",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-06-02",
|
||||||
|
"name": "Spring Bank Holiday",
|
||||||
|
"local_name": "Spring Bank Holiday",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-06-03",
|
||||||
|
"name": "Queen’s Platinum Jubilee",
|
||||||
|
"local_name": "Queen’s Platinum Jubilee",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-07-12",
|
||||||
|
"name": "Battle of the Boyne",
|
||||||
|
"local_name": "Battle of the Boyne",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-NIR"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-08-01",
|
||||||
|
"name": "Summer Bank Holiday",
|
||||||
|
"local_name": "Summer Bank Holiday",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-SCT"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-08-29",
|
||||||
|
"name": "Summer Bank Holiday",
|
||||||
|
"local_name": "Summer Bank Holiday",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-ENG",
|
||||||
|
"GB-WLS",
|
||||||
|
"GB-NIR"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-11-30",
|
||||||
|
"name": "Saint Andrew's Day",
|
||||||
|
"local_name": "Saint Andrew's Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [
|
||||||
|
"GB-SCT"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-12-26",
|
||||||
|
"name": "St. Stephen's Day",
|
||||||
|
"local_name": "Boxing Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2022-12-27",
|
||||||
|
"name": "Christmas Day",
|
||||||
|
"local_name": "Christmas Day",
|
||||||
|
"country_code": "GB",
|
||||||
|
"regions": [],
|
||||||
|
"types": [
|
||||||
|
"Public"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
2
holidays/generate.go
Normal file
2
holidays/generate.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
package main
|
||||||
|
//go:generate make proto
|
||||||
126
holidays/handler/holidays.go
Normal file
126
holidays/handler/holidays.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/micro/micro/v3/service/config"
|
||||||
|
"github.com/micro/micro/v3/service/errors"
|
||||||
|
log "github.com/micro/micro/v3/service/logger"
|
||||||
|
|
||||||
|
pb "github.com/micro/services/holidays/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Holidays struct {
|
||||||
|
conf conf
|
||||||
|
}
|
||||||
|
|
||||||
|
type conf struct {
|
||||||
|
NagerHost string `json:"nager_host"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Holidays {
|
||||||
|
val, err := config.Get("micro.holidays")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to load config %s", err)
|
||||||
|
}
|
||||||
|
var conf conf
|
||||||
|
if err := val.Scan(&conf); err != nil {
|
||||||
|
log.Fatalf("Failed to load config %s", err)
|
||||||
|
}
|
||||||
|
if len(conf.NagerHost) == 0 {
|
||||||
|
log.Fatalf("Nager host not configured")
|
||||||
|
}
|
||||||
|
return &Holidays{conf: conf}
|
||||||
|
}
|
||||||
|
|
||||||
|
type nagerCountry struct {
|
||||||
|
CountryCode string `json:"countryCode"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Holidays) Countries(ctx context.Context, request *pb.CountriesRequest, response *pb.CountriesResponse) error {
|
||||||
|
rsp, err := http.Get(h.conf.NagerHost + "/api/v3/AvailableCountries")
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error listing available countries %s", err)
|
||||||
|
return errors.InternalServerError("holidays.countries", "Error retrieving country list")
|
||||||
|
}
|
||||||
|
defer rsp.Body.Close()
|
||||||
|
if rsp.StatusCode != 200 {
|
||||||
|
log.Errorf("Error listing available countries %s", rsp.Status)
|
||||||
|
return errors.InternalServerError("holidays.countries", "Error retrieving country list")
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadAll(rsp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error processing available countries %s", err)
|
||||||
|
return errors.InternalServerError("holidays.countries", "Error retrieving country list")
|
||||||
|
}
|
||||||
|
var rspArr []nagerCountry
|
||||||
|
if err := json.Unmarshal(b, &rspArr); err != nil {
|
||||||
|
log.Errorf("Error processing available countries %s", err)
|
||||||
|
return errors.InternalServerError("holidays.countries", "Error retrieving country list")
|
||||||
|
}
|
||||||
|
response.Countries = make([]*pb.Country, len(rspArr))
|
||||||
|
for i, c := range rspArr {
|
||||||
|
response.Countries[i] = &pb.Country{
|
||||||
|
Code: c.CountryCode,
|
||||||
|
Name: c.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type nagerHoliday struct {
|
||||||
|
Date string `json:"date"`
|
||||||
|
LocalName string `json:"localName"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
CountryCode string `json:"countryCode"`
|
||||||
|
Counties []string `json:"counties"`
|
||||||
|
Types []string `json:"types"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Holidays) List(ctx context.Context, request *pb.ListRequest, response *pb.ListResponse) error {
|
||||||
|
if request.Year == 0 {
|
||||||
|
return errors.BadRequest("holidays.list", "Missing year argument")
|
||||||
|
}
|
||||||
|
if len(request.CountryCode) == 0 {
|
||||||
|
return errors.BadRequest("holidays.list", "Missing country code argument")
|
||||||
|
}
|
||||||
|
rsp, err := http.Get(fmt.Sprintf("%s/api/v3/PublicHolidays/%d/%s", h.conf.NagerHost, request.Year, request.CountryCode))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error listing available countries %s", err)
|
||||||
|
return errors.InternalServerError("holidays.list", "Error retrieving holidays list")
|
||||||
|
}
|
||||||
|
defer rsp.Body.Close()
|
||||||
|
if rsp.StatusCode != 200 {
|
||||||
|
log.Errorf("Error listing holidays %s", rsp.Status)
|
||||||
|
return errors.InternalServerError("holidays.list", "Error retrieving holidays list")
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadAll(rsp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error processing holidays %s", err)
|
||||||
|
return errors.InternalServerError("holidays.countries", "Error retrieving holidays list")
|
||||||
|
}
|
||||||
|
var rspArr []nagerHoliday
|
||||||
|
if err := json.Unmarshal(b, &rspArr); err != nil {
|
||||||
|
log.Errorf("Error processing holidays %s", err)
|
||||||
|
return errors.InternalServerError("holidays.countries", "Error retrieving holidays list")
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Holidays = make([]*pb.Holiday, len(rspArr))
|
||||||
|
for i, c := range rspArr {
|
||||||
|
response.Holidays[i] = &pb.Holiday{
|
||||||
|
Date: c.Date,
|
||||||
|
Name: c.Name,
|
||||||
|
LocalName: c.LocalName,
|
||||||
|
CountryCode: c.CountryCode,
|
||||||
|
Regions: c.Counties,
|
||||||
|
Types: c.Types,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
25
holidays/main.go
Normal file
25
holidays/main.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/micro/services/holidays/handler"
|
||||||
|
pb "github.com/micro/services/holidays/proto"
|
||||||
|
|
||||||
|
"github.com/micro/micro/v3/service"
|
||||||
|
"github.com/micro/micro/v3/service/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Create service
|
||||||
|
srv := service.New(
|
||||||
|
service.Name("holidays"),
|
||||||
|
service.Version("latest"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register handler
|
||||||
|
pb.RegisterHolidaysHandler(srv.Server(), handler.New())
|
||||||
|
|
||||||
|
// Run service
|
||||||
|
if err := srv.Run(); err != nil {
|
||||||
|
logger.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
1
holidays/micro.mu
Normal file
1
holidays/micro.mu
Normal file
@@ -0,0 +1 @@
|
|||||||
|
service holidays
|
||||||
40
holidays/nager-k8s.yaml
Normal file
40
holidays/nager-k8s.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nager-latest
|
||||||
|
labels:
|
||||||
|
app: nager
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nager
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nager
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nager
|
||||||
|
image: nager/nager-date:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
env:
|
||||||
|
- name: EnableCors
|
||||||
|
value: "true"
|
||||||
|
- name: EnableIpRateLimiting
|
||||||
|
value: "false"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nager
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nager
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
540
holidays/proto/holidays.pb.go
Normal file
540
holidays/proto/holidays.pb.go
Normal file
@@ -0,0 +1,540 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.26.0
|
||||||
|
// protoc v3.15.5
|
||||||
|
// source: proto/holidays.proto
|
||||||
|
|
||||||
|
package holidays
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type CountriesRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CountriesRequest) Reset() {
|
||||||
|
*x = CountriesRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CountriesRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CountriesRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CountriesRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use CountriesRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CountriesRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_holidays_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CountriesResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Countries []*Country `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CountriesResponse) Reset() {
|
||||||
|
*x = CountriesResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CountriesResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CountriesResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CountriesResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use CountriesResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CountriesResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_holidays_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CountriesResponse) GetCountries() []*Country {
|
||||||
|
if x != nil {
|
||||||
|
return x.Countries
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Country struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
|
// The English name of the country
|
||||||
|
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Country) Reset() {
|
||||||
|
*x = Country{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Country) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Country) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Country) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Country.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Country) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_holidays_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Country) GetCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Code
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Country) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
||||||
|
// The year to list holidays for
|
||||||
|
Year int64 `protobuf:"varint,2,opt,name=year,proto3" json:"year,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListRequest) Reset() {
|
||||||
|
*x = ListRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_holidays_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListRequest) GetCountryCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CountryCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListRequest) GetYear() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Year
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Holidays []*Holiday `protobuf:"bytes,1,rep,name=holidays,proto3" json:"holidays,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListResponse) Reset() {
|
||||||
|
*x = ListResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_holidays_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListResponse) GetHolidays() []*Holiday {
|
||||||
|
if x != nil {
|
||||||
|
return x.Holidays
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Holiday struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// date of the holiday in yyyy-mm-dd format
|
||||||
|
Date string `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"`
|
||||||
|
// the name of the holiday in English
|
||||||
|
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
// the local name of the holiday
|
||||||
|
LocalName string `protobuf:"bytes,3,opt,name=local_name,json=localName,proto3" json:"local_name,omitempty"`
|
||||||
|
// the country this holiday occurs in
|
||||||
|
CountryCode string `protobuf:"bytes,4,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
||||||
|
// the regions within the country that observe this holiday (if not all of them)
|
||||||
|
Regions []string `protobuf:"bytes,5,rep,name=regions,proto3" json:"regions,omitempty"`
|
||||||
|
// the type of holiday Public, Bank, School, Authorities, Optional, Observance
|
||||||
|
Types []string `protobuf:"bytes,6,rep,name=types,proto3" json:"types,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) Reset() {
|
||||||
|
*x = Holiday{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Holiday) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Holiday) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_holidays_proto_msgTypes[5]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Holiday.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Holiday) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_holidays_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) GetDate() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Date
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) GetLocalName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalName
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) GetCountryCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CountryCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) GetRegions() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Regions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Holiday) GetTypes() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Types
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_proto_holidays_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_proto_holidays_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x14, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73,
|
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73,
|
||||||
|
0x22, 0x12, 0x0a, 0x10, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x22, 0x44, 0x0a, 0x11, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65,
|
||||||
|
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x6f, 0x75,
|
||||||
|
0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x68,
|
||||||
|
0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||||
|
0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x31, 0x0a, 0x07, 0x43, 0x6f,
|
||||||
|
0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
|
||||||
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x44, 0x0a,
|
||||||
|
0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c,
|
||||||
|
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12,
|
||||||
|
0x12, 0x0a, 0x04, 0x79, 0x65, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x79,
|
||||||
|
0x65, 0x61, 0x72, 0x22, 0x3d, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
|
0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73, 0x18,
|
||||||
|
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73,
|
||||||
|
0x2e, 0x48, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x52, 0x08, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61,
|
||||||
|
0x79, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x07, 0x48, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x12, 0x12,
|
||||||
|
0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61,
|
||||||
|
0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f,
|
||||||
|
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
|
0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79,
|
||||||
|
0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75,
|
||||||
|
0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69,
|
||||||
|
0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f,
|
||||||
|
0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
|
||||||
|
0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x32, 0x8b, 0x01, 0x0a, 0x08, 0x48, 0x6f, 0x6c,
|
||||||
|
0x69, 0x64, 0x61, 0x79, 0x73, 0x12, 0x46, 0x0a, 0x09, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69,
|
||||||
|
0x65, 0x73, 0x12, 0x1a, 0x2e, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73, 0x2e, 0x43, 0x6f,
|
||||||
|
0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
|
||||||
|
0x2e, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72,
|
||||||
|
0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a,
|
||||||
|
0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73,
|
||||||
|
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68,
|
||||||
|
0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
|
||||||
|
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x12, 0x5a, 0x10, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x3b, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_proto_holidays_proto_rawDescOnce sync.Once
|
||||||
|
file_proto_holidays_proto_rawDescData = file_proto_holidays_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_proto_holidays_proto_rawDescGZIP() []byte {
|
||||||
|
file_proto_holidays_proto_rawDescOnce.Do(func() {
|
||||||
|
file_proto_holidays_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_holidays_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_proto_holidays_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_proto_holidays_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||||
|
var file_proto_holidays_proto_goTypes = []interface{}{
|
||||||
|
(*CountriesRequest)(nil), // 0: holidays.CountriesRequest
|
||||||
|
(*CountriesResponse)(nil), // 1: holidays.CountriesResponse
|
||||||
|
(*Country)(nil), // 2: holidays.Country
|
||||||
|
(*ListRequest)(nil), // 3: holidays.ListRequest
|
||||||
|
(*ListResponse)(nil), // 4: holidays.ListResponse
|
||||||
|
(*Holiday)(nil), // 5: holidays.Holiday
|
||||||
|
}
|
||||||
|
var file_proto_holidays_proto_depIdxs = []int32{
|
||||||
|
2, // 0: holidays.CountriesResponse.countries:type_name -> holidays.Country
|
||||||
|
5, // 1: holidays.ListResponse.holidays:type_name -> holidays.Holiday
|
||||||
|
0, // 2: holidays.Holidays.Countries:input_type -> holidays.CountriesRequest
|
||||||
|
3, // 3: holidays.Holidays.List:input_type -> holidays.ListRequest
|
||||||
|
1, // 4: holidays.Holidays.Countries:output_type -> holidays.CountriesResponse
|
||||||
|
4, // 5: holidays.Holidays.List:output_type -> holidays.ListResponse
|
||||||
|
4, // [4:6] is the sub-list for method output_type
|
||||||
|
2, // [2:4] is the sub-list for method input_type
|
||||||
|
2, // [2:2] is the sub-list for extension type_name
|
||||||
|
2, // [2:2] is the sub-list for extension extendee
|
||||||
|
0, // [0:2] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_proto_holidays_proto_init() }
|
||||||
|
func file_proto_holidays_proto_init() {
|
||||||
|
if File_proto_holidays_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_proto_holidays_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*CountriesRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proto_holidays_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*CountriesResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proto_holidays_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Country); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proto_holidays_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proto_holidays_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proto_holidays_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Holiday); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_proto_holidays_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 6,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_proto_holidays_proto_goTypes,
|
||||||
|
DependencyIndexes: file_proto_holidays_proto_depIdxs,
|
||||||
|
MessageInfos: file_proto_holidays_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_proto_holidays_proto = out.File
|
||||||
|
file_proto_holidays_proto_rawDesc = nil
|
||||||
|
file_proto_holidays_proto_goTypes = nil
|
||||||
|
file_proto_holidays_proto_depIdxs = nil
|
||||||
|
}
|
||||||
114
holidays/proto/holidays.pb.micro.go
Normal file
114
holidays/proto/holidays.pb.micro.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||||
|
// source: proto/holidays.proto
|
||||||
|
|
||||||
|
package holidays
|
||||||
|
|
||||||
|
import (
|
||||||
|
fmt "fmt"
|
||||||
|
proto "github.com/golang/protobuf/proto"
|
||||||
|
math "math"
|
||||||
|
)
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
api "github.com/micro/micro/v3/service/api"
|
||||||
|
client "github.com/micro/micro/v3/service/client"
|
||||||
|
server "github.com/micro/micro/v3/service/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ api.Endpoint
|
||||||
|
var _ context.Context
|
||||||
|
var _ client.Option
|
||||||
|
var _ server.Option
|
||||||
|
|
||||||
|
// Api Endpoints for Holidays service
|
||||||
|
|
||||||
|
func NewHolidaysEndpoints() []*api.Endpoint {
|
||||||
|
return []*api.Endpoint{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client API for Holidays service
|
||||||
|
|
||||||
|
type HolidaysService interface {
|
||||||
|
// Get the list of countries that are supported by this API
|
||||||
|
Countries(ctx context.Context, in *CountriesRequest, opts ...client.CallOption) (*CountriesResponse, error)
|
||||||
|
// List the holiday dates for a given country and year
|
||||||
|
List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type holidaysService struct {
|
||||||
|
c client.Client
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHolidaysService(name string, c client.Client) HolidaysService {
|
||||||
|
return &holidaysService{
|
||||||
|
c: c,
|
||||||
|
name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *holidaysService) Countries(ctx context.Context, in *CountriesRequest, opts ...client.CallOption) (*CountriesResponse, error) {
|
||||||
|
req := c.c.NewRequest(c.name, "Holidays.Countries", in)
|
||||||
|
out := new(CountriesResponse)
|
||||||
|
err := c.c.Call(ctx, req, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *holidaysService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) {
|
||||||
|
req := c.c.NewRequest(c.name, "Holidays.List", in)
|
||||||
|
out := new(ListResponse)
|
||||||
|
err := c.c.Call(ctx, req, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server API for Holidays service
|
||||||
|
|
||||||
|
type HolidaysHandler interface {
|
||||||
|
// Get the list of countries that are supported by this API
|
||||||
|
Countries(context.Context, *CountriesRequest, *CountriesResponse) error
|
||||||
|
// List the holiday dates for a given country and year
|
||||||
|
List(context.Context, *ListRequest, *ListResponse) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterHolidaysHandler(s server.Server, hdlr HolidaysHandler, opts ...server.HandlerOption) error {
|
||||||
|
type holidays interface {
|
||||||
|
Countries(ctx context.Context, in *CountriesRequest, out *CountriesResponse) error
|
||||||
|
List(ctx context.Context, in *ListRequest, out *ListResponse) error
|
||||||
|
}
|
||||||
|
type Holidays struct {
|
||||||
|
holidays
|
||||||
|
}
|
||||||
|
h := &holidaysHandler{hdlr}
|
||||||
|
return s.Handle(s.NewHandler(&Holidays{h}, opts...))
|
||||||
|
}
|
||||||
|
|
||||||
|
type holidaysHandler struct {
|
||||||
|
HolidaysHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *holidaysHandler) Countries(ctx context.Context, in *CountriesRequest, out *CountriesResponse) error {
|
||||||
|
return h.HolidaysHandler.Countries(ctx, in, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *holidaysHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error {
|
||||||
|
return h.HolidaysHandler.List(ctx, in, out)
|
||||||
|
}
|
||||||
52
holidays/proto/holidays.proto
Normal file
52
holidays/proto/holidays.proto
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package holidays;
|
||||||
|
|
||||||
|
option go_package = "./proto;holidays";
|
||||||
|
|
||||||
|
service Holidays {
|
||||||
|
// Get the list of countries that are supported by this API
|
||||||
|
rpc Countries(CountriesRequest) returns (CountriesResponse) {}
|
||||||
|
// List the holiday dates for a given country and year
|
||||||
|
rpc List(ListRequest) returns (ListResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message CountriesRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message CountriesResponse {
|
||||||
|
repeated Country countries = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Country {
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
string code = 1;
|
||||||
|
// The English name of the country
|
||||||
|
string name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListRequest {
|
||||||
|
// The 2 letter country code (as defined in ISO 3166-1 alpha-2)
|
||||||
|
string country_code = 1;
|
||||||
|
// The year to list holidays for
|
||||||
|
int64 year = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListResponse {
|
||||||
|
repeated Holiday holidays = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Holiday {
|
||||||
|
// date of the holiday in yyyy-mm-dd format
|
||||||
|
string date = 1;
|
||||||
|
// the name of the holiday in English
|
||||||
|
string name = 2;
|
||||||
|
// the local name of the holiday
|
||||||
|
string local_name = 3;
|
||||||
|
// the country this holiday occurs in
|
||||||
|
string country_code = 4;
|
||||||
|
// the regions within the country that observe this holiday (if not all of them)
|
||||||
|
repeated string regions = 5;
|
||||||
|
// the type of holiday Public, Bank, School, Authorities, Optional, Observance
|
||||||
|
repeated string types = 6;
|
||||||
|
}
|
||||||
5
holidays/publicapi.json
Normal file
5
holidays/publicapi.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "holidays",
|
||||||
|
"icon": "🏖️",
|
||||||
|
"category": "util"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user