Commit 606b13d2 authored by Peter Cheng's avatar Peter Cheng

追加休假日期計算

parent 32adfef5
// Code generated by protoc-gen-go.
// source: punchclock.proto
// DO NOT EDIT!
/*
Package beans is a generated protocol buffer package.
It is generated from these files:
punchclock.proto
redis.proto
sendMail.proto
It has these top-level messages:
Punchclock
TimeStruct
Redis
SendMail
*/
package beans
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// 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.ProtoPackageIsVersion2 // please upgrade the proto package
type Punchclock struct {
Begin *TimeStruct `protobuf:"bytes,7,opt,name=Begin" json:"begin"`
End *TimeStruct `protobuf:"bytes,8,opt,name=End" json:"end"`
}
func (m *Punchclock) Reset() { *m = Punchclock{} }
func (m *Punchclock) String() string { return proto.CompactTextString(m) }
func (*Punchclock) ProtoMessage() {}
func (*Punchclock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Punchclock) GetBegin() *TimeStruct {
if m != nil {
return m.Begin
}
return nil
}
func (m *Punchclock) GetEnd() *TimeStruct {
if m != nil {
return m.End
}
return nil
}
type TimeStruct struct {
Year string `protobuf:"bytes,1,opt,name=Year" json:"year"`
Month string `protobuf:"bytes,2,opt,name=Month" json:"month"`
Day string `protobuf:"bytes,3,opt,name=Day" json:"day"`
Hour string `protobuf:"bytes,4,opt,name=Hour" json:"hour"`
Minute string `protobuf:"bytes,5,opt,name=Minute" json:"minute"`
Second string `protobuf:"bytes,6,opt,name=Second" json:"second"`
}
func (m *TimeStruct) Reset() { *m = TimeStruct{} }
func (m *TimeStruct) String() string { return proto.CompactTextString(m) }
func (*TimeStruct) ProtoMessage() {}
func (*TimeStruct) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *TimeStruct) GetYear() string {
if m != nil {
return m.Year
}
return ""
}
func (m *TimeStruct) GetMonth() string {
if m != nil {
return m.Month
}
return ""
}
func (m *TimeStruct) GetDay() string {
if m != nil {
return m.Day
}
return ""
}
func (m *TimeStruct) GetHour() string {
if m != nil {
return m.Hour
}
return ""
}
func (m *TimeStruct) GetMinute() string {
if m != nil {
return m.Minute
}
return ""
}
func (m *TimeStruct) GetSecond() string {
if m != nil {
return m.Second
}
return ""
}
func init() {
proto.RegisterType((*Punchclock)(nil), "beans.Punchclock")
proto.RegisterType((*TimeStruct)(nil), "beans.TimeStruct")
}
func init() { proto.RegisterFile("punchclock.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 200 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x28, 0x28, 0xcd, 0x4b,
0xce, 0x48, 0xce, 0xc9, 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4d, 0x4a,
0x4d, 0xcc, 0x2b, 0x56, 0x8a, 0xe2, 0xe2, 0x0a, 0x80, 0x4b, 0x09, 0xa9, 0x73, 0xb1, 0x3a, 0xa5,
0xa6, 0x67, 0xe6, 0x49, 0xb0, 0x2b, 0x30, 0x6a, 0x70, 0x1b, 0x09, 0xea, 0x81, 0x15, 0xe9, 0x85,
0x64, 0xe6, 0xa6, 0x06, 0x97, 0x14, 0x95, 0x26, 0x97, 0x04, 0x41, 0xe4, 0x85, 0x94, 0xb9, 0x98,
0x5d, 0xf3, 0x52, 0x24, 0x38, 0x70, 0x29, 0x03, 0xc9, 0x2a, 0xf5, 0x30, 0x72, 0x71, 0x21, 0xc4,
0x84, 0x84, 0xb8, 0x58, 0x22, 0x53, 0x13, 0x8b, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0xc0,
0x6c, 0x21, 0x11, 0x2e, 0x56, 0xdf, 0xfc, 0xbc, 0x92, 0x0c, 0x09, 0x26, 0xb0, 0x20, 0x84, 0x23,
0x24, 0xc0, 0xc5, 0xec, 0x92, 0x58, 0x29, 0xc1, 0x0c, 0x16, 0x03, 0x31, 0x41, 0x7a, 0x3d, 0xf2,
0x4b, 0x8b, 0x24, 0x58, 0x20, 0x7a, 0x41, 0x6c, 0x21, 0x31, 0x2e, 0x36, 0xdf, 0xcc, 0xbc, 0xd2,
0x92, 0x54, 0x09, 0x56, 0xb0, 0x28, 0x94, 0x07, 0x12, 0x0f, 0x4e, 0x4d, 0xce, 0xcf, 0x4b, 0x91,
0x60, 0x83, 0x88, 0x43, 0x78, 0x49, 0x6c, 0x60, 0x8f, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff,
0x05, 0x73, 0xab, 0x0e, 0x0c, 0x01, 0x00, 0x00,
}
syntax = "proto3";
package beans;
message Punchclock {
TimeStruct Begin = 7; //`json:"begin"`
TimeStruct End = 8; //`json:"end"`
}
message TimeStruct {
string Year = 1; //`json:"year"`
string Month = 2; //`json:"month"`
string Day = 3; //`json:"day"`
string Hour = 4; //`json:"hour"`
string Minute = 5; //`json:"minute"`
string Second = 6; //`json:"second"`
}
\ No newline at end of file
......@@ -2,17 +2,6 @@
// source: redis.proto
// DO NOT EDIT!
/*
Package beans is a generated protocol buffer package.
It is generated from these files:
redis.proto
sendMail.proto
It has these top-level messages:
Redis
SendMail
*/
package beans
import proto "github.com/golang/protobuf/proto"
......@@ -24,22 +13,16 @@ 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.ProtoPackageIsVersion2 // please upgrade the proto package
type Redis struct {
Key string `protobuf:"bytes,1,opt,name=Key" json:"key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=Value" json:"value,omitempty"`
Hkey string `protobuf:"bytes,3,opt,name=Hkey" json:"hkey,omitempty"`
Key string `protobuf:"bytes,1,opt,name=Key" json:"key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=Value" json:"value,omitempty"`
Hkey string `protobuf:"bytes,3,opt,name=Hkey" json:"hkey,omitempty"`
}
func (m *Redis) Reset() { *m = Redis{} }
func (m *Redis) String() string { return proto.CompactTextString(m) }
func (*Redis) ProtoMessage() {}
func (*Redis) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (*Redis) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (m *Redis) GetKey() string {
if m != nil {
......@@ -66,9 +49,9 @@ func init() {
proto.RegisterType((*Redis)(nil), "beans.Redis")
}
func init() { proto.RegisterFile("redis.proto", fileDescriptor0) }
func init() { proto.RegisterFile("redis.proto", fileDescriptor1) }
var fileDescriptor0 = []byte{
var fileDescriptor1 = []byte{
// 100 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0x4a, 0x4d, 0xc9,
0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4d, 0x4a, 0x4d, 0xcc, 0x2b, 0x56, 0x72,
......
......@@ -14,16 +14,16 @@ var _ = fmt.Errorf
var _ = math.Inf
type SendMail struct {
To string ` protobuf:"bytes,1,opt,name=To" json:"To,omitempty" form:"to"`
Cc string ` protobuf:"bytes,2,opt,name=Cc" json:"Cc,omitempty" form:"cc"`
Subject string ` protobuf:"bytes,3,opt,name=Subject" json:"Subject,omitempty" form:"subject"`
Content string ` protobuf:"bytes,4,opt,name=Content" json:"Content,omitempty" form:"content"`
To string ` protobuf:"bytes,1,opt,name=To" json:"To,omitempty" form:"to"`
Cc string ` protobuf:"bytes,2,opt,name=Cc" json:"Cc,omitempty" form:"cc"`
Subject string ` protobuf:"bytes,3,opt,name=Subject" json:"Subject,omitempty" form:"subject"`
Content string ` protobuf:"bytes,4,opt,name=Content" json:"Content,omitempty" form:"content"`
}
func (m *SendMail) Reset() { *m = SendMail{} }
func (m *SendMail) String() string { return proto.CompactTextString(m) }
func (*SendMail) ProtoMessage() {}
func (*SendMail) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (*SendMail) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
func (m *SendMail) GetTo() string {
if m != nil {
......@@ -57,9 +57,9 @@ func init() {
proto.RegisterType((*SendMail)(nil), "beans.SendMail")
}
func init() { proto.RegisterFile("sendMail.proto", fileDescriptor1) }
func init() { proto.RegisterFile("sendMail.proto", fileDescriptor2) }
var fileDescriptor1 = []byte{
var fileDescriptor2 = []byte{
// 116 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x4e, 0xcd, 0x4b,
0xf1, 0x4d, 0xcc, 0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4d, 0x4a, 0x4d, 0xcc,
......
package controllers
import (
"log"
"net/http"
"strconv"
"time"
"unicode/utf8"
"github.com/gin-gonic/gin"
"github.com/teed7334-restore/homekeeper/beans"
"github.com/teed7334-restore/homekeeper/env"
"github.com/teed7334-restore/homekeeper/models"
)
//CalcTime 計算時數
func CalcTime(c *gin.Context) {
params := getPunchclockParams(c)
beginYear := params.GetBegin().GetYear()
beginMonth := params.GetBegin().GetMonth()
beginDay := params.GetBegin().GetDay()
beginHour := params.GetBegin().GetHour()
beginMinute := params.GetBegin().GetMinute()
endYear := params.GetEnd().GetYear()
endMonth := params.GetEnd().GetMonth()
endDay := params.GetEnd().GetDay()
endHour := params.GetEnd().GetHour()
endMinute := params.GetEnd().GetMinute()
beginTime, _ := strconv.Atoi(beginHour + beginMinute)
endTime, _ := strconv.Atoi(endHour + endMinute)
diffDay := 0
diffHour := 0
diffMinute := 0
beginHour, beginMinute, endHour, endMinute = changeToLunchTime(beginTime, endTime, beginHour, beginMinute, endHour, endMinute)
if isSameDay(params) { //只請當天
if beginTime < 1200 && endTime > 1330 { //有跨午休
diffHour, diffMinute = calcTimeBlock(beginHour, endHour, beginMinute, endMinute, true)
} else { //沒跨午休
diffHour, diffMinute = calcTimeBlock(beginHour, endHour, beginMinute, endMinute, false)
}
_beginMonth := appendZero(beginMonth)
_beginDay := appendZero(beginDay)
if isHoliday(beginYear, _beginMonth, _beginDay) {
diffDay = 0
diffHour = 0
diffMinute = 0
}
} else { //跨日
_diffHour := 0
_diffMinute := 0
if beginTime < 1200 { //有跨午休
_diffHour, _diffMinute = calcTimeBlock(beginHour, "18", beginMinute, "0", true)
} else { //沒跨午休
_diffHour, _diffMinute = calcTimeBlock(beginHour, "18", beginMinute, "0", false)
}
diffDay = calcDate(beginYear, beginMonth, beginDay, endYear, endMonth, endDay)
if endTime < 1200 { //有跨午休
diffHour, diffMinute = calcTimeBlock("8", endHour, "30", endMinute, true)
} else { //沒跨午休
diffHour, diffMinute = calcTimeBlock("8", endHour, "30", endMinute, false)
}
diffHour = diffHour + _diffHour
diffMinute = diffMinute + _diffMinute
}
c.JSON(http.StatusOK, gin.H{"diffDay": diffDay, "diffHour": diffHour, "diffMinute": diffMinute})
}
func getHoliday() map[string]int {
cfg := env.GetEnv()
list := models.GetHoliday()
data := make(map[string]int)
for _, item := range list {
key := item.Date.Format(cfg.TimeFormat)
data[key] = 1
}
return data
}
func appendZero(value string) string {
if 2 > utf8.RuneCountInString(value) {
value = "0" + value
}
return value
}
func isHoliday(year string, month string, day string) bool {
cfg := env.GetEnv()
list := getHoliday()
checkTime := year + "-" + month + "-" + day + " 00:00:00"
begin, _ := time.ParseInLocation(cfg.TimeFormat, checkTime, time.Local)
_, ok := list[begin.Format(cfg.TimeFormat)]
if ok {
return true
}
return false
}
func calcDate(beginYear string, beginMonth string, beginDay string, endYear string, endMonth string, endDay string) int {
cfg := env.GetEnv()
diffDay := 0
_beginMonth := appendZero(beginMonth)
_beginDay := appendZero(beginDay)
_endMonth := appendZero(endMonth)
_endDay := appendZero(endDay)
checkTime := beginYear + "-" + _beginMonth + "-" + _beginDay + " 00:00:00"
begin, _ := time.ParseInLocation(cfg.TimeFormat, checkTime, time.Local)
checkTime = endYear + "-" + _endMonth + "-" + _endDay + " 00:00:00"
end, _ := time.ParseInLocation(cfg.TimeFormat, checkTime, time.Local)
if begin.Before(end) {
for {
if isHoliday(beginYear, _beginMonth, _beginDay) {
add, _ := time.ParseDuration("24h")
begin = begin.Add(add)
continue
}
if !begin.Before(end) {
break
}
add, _ := time.ParseDuration("24h")
begin = begin.Add(add)
diffDay++
}
}
return diffDay
}
func calcTimeBlock(beginHour string, endHour string, beginMinute string, endMinute string, haveLunchTime bool) (diffHour int, diffMinute int) {
_beginHour, _ := strconv.Atoi(beginHour)
_endHour, _ := strconv.Atoi(endHour)
_beginMinute, _ := strconv.Atoi(beginMinute)
_endMinute, _ := strconv.Atoi(endMinute)
diffHour = _endHour - _beginHour
diffMinute = diffHour*60 + _endMinute - _beginMinute
if haveLunchTime {
diffMinute = diffMinute - 90
}
diffHour = diffMinute / 60
diffMinute = diffMinute % 60
return diffHour, diffMinute
}
func changeToLunchTime(beginTime int, endTime int, beginHour string, beginMinute string, endHour string, endMinute string) (string, string, string, string) {
if beginTime >= 1200 && beginTime <= 1330 { //當啟始時間於午休區間時
beginHour = "13"
beginMinute = "30"
}
if endTime >= 1200 && endTime <= 1330 { //當結束時間於午休區間時
endHour = "13"
endMinute = "30"
}
return beginHour, beginMinute, endHour, endMinute
}
func isSameDay(pc *beans.Punchclock) bool {
begin := pc.GetBegin().GetYear() + pc.GetBegin().GetMonth() + pc.GetBegin().GetDay()
end := pc.GetEnd().GetYear() + pc.GetEnd().GetMonth() + pc.GetEnd().GetDay()
return begin == end
}
func getPunchclockParams(c *gin.Context) *beans.Punchclock {
params := &beans.Punchclock{}
err := c.BindJSON(params)
if err != nil {
log.Println(err)
}
return params
}
......@@ -15,7 +15,7 @@ import (
//GetRedis 取得Redis資料
func GetRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := redis.String(client.Do("get", params.GetKey()))
if err != nil {
......@@ -27,7 +27,7 @@ func GetRedis(c *gin.Context) {
//SetRedis 設定Redis資料
func SetRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("set", params.GetKey(), params.GetValue())
if err != nil {
......@@ -39,7 +39,7 @@ func SetRedis(c *gin.Context) {
//IncrRedis 對Redis資料進行遞增
func IncrRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("incr", params.GetKey())
if err != nil {
......@@ -51,7 +51,7 @@ func IncrRedis(c *gin.Context) {
//DecrRedis 對Redis資料進行遞減
func DecrRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("decr", params.GetKey())
if err != nil {
......@@ -63,7 +63,7 @@ func DecrRedis(c *gin.Context) {
//HSetRedis 對Redis資料建立Hashmap
func HSetRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("hset", params.GetKey(), params.GetHkey(), params.GetValue())
if err != nil {
......@@ -75,7 +75,7 @@ func HSetRedis(c *gin.Context) {
//HGetRedis 取得建立Hashmap的Redis資料
func HGetRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := redis.String(client.Do("hget", params.GetKey(), params.GetHkey()))
if err != nil {
......@@ -87,7 +87,7 @@ func HGetRedis(c *gin.Context) {
//SAddRedis 對Redis進行資料添加,並排除重複項目
func SAddRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("sadd", params.GetKey(), params.GetValue())
if err != nil {
......@@ -99,7 +99,7 @@ func SAddRedis(c *gin.Context) {
//SCardRedis 取得Key中的資料集合總數
func SCardRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("scard", params.GetKey())
if err != nil {
......@@ -111,7 +111,7 @@ func SCardRedis(c *gin.Context) {
//LPushRedis 對Redis中List資料的前面做資料添加
func LPushRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("lpush", params.GetKey(), params.GetValue())
if err != nil {
......@@ -123,7 +123,7 @@ func LPushRedis(c *gin.Context) {
//RPushRedis 對Redis中List資料的後面做資料添加
func RPushRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("rpush", params.GetKey(), params.GetValue())
if err != nil {
......@@ -135,7 +135,7 @@ func RPushRedis(c *gin.Context) {
//LSetRedis 從Redis中List資料的第...列做資料修改
func LSetRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
client := initRedis()
value, err := client.Do("lset", params.GetKey(), params.GetHkey(), params.GetValue())
if err != nil {
......@@ -147,7 +147,7 @@ func LSetRedis(c *gin.Context) {
//LRangeRedis 取得Redis中List特定範圍裡面的資料
func LRangeRedis(c *gin.Context) {
params := getParams(c)
params := getRedisParams(c)
getRange := strings.Split(params.GetValue(), ":")
begin := getRange[0]
end := getRange[1]
......@@ -169,7 +169,7 @@ func initRedis() redis.Conn {
return client
}
func getParams(c *gin.Context) *beans.Redis {
func getRedisParams(c *gin.Context) *beans.Redis {
params := &beans.Redis{}
err := c.BindJSON(params)
if err != nil {
......
package database
import (
"fmt"
"github.com/teed7334-restore/homekeeper/env"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
//Db 資料庫連結器
var Db *gorm.DB
//Err 錯誤處理器
var Err error
func init() {
db := env.GetEnv().Database
dsn := fmt.Sprintf("%s:%s@(%s)/%s?charset=%s&parseTime=%s&loc=%s", db.User, db.Password, db.Host, db.Database, db.Charset, db.ParseTime, db.Loc)
Db, Err = gorm.Open("mysql", dsn)
if Err != nil {
panic(Err)
}
}
......@@ -4,13 +4,26 @@ package env
type Config struct {
Env string
TimeFormat string
Mail struct {
Database struct {
Host string
User string
Password string
Database string
Charset string
ParseTime string
Loc string
}
Mail struct {
Host string
Port int
From string
User string
Password string
}
Redis struct {
Host string
Protocol string
}
}
var cfg = &Config{}
......@@ -18,11 +31,20 @@ var cfg = &Config{}
func init() {
cfg.Env = "release"
cfg.TimeFormat = "2006-01-02 15:04:05"
cfg.Database.User = ""
cfg.Database.Password = ""
cfg.Database.Host = ""
cfg.Database.Database = ""
cfg.Database.Charset = "utf8mb4"
cfg.Database.ParseTime = "true"
cfg.Database.Loc = "Local"
cfg.Mail.Host = ""
cfg.Mail.Port = 25
cfg.Mail.From = ""
cfg.Mail.User = ""
cfg.Mail.Password = ""
cfg.Redis.Host = "127.0.0.1:6379"
cfg.Redis.Protocol = "tcp"
}
//GetEnv 取得環境參數
......
package models
import (
"log"
"time"
db "github.com/teed7334-restore/homekeeper/database"
)
//Holiday 假期資料表
type Holiday struct {
ID int `gorm:"AUTO_INCREMENT"`
Date time.Time
Name string
IsHoliday int
HolidayCategory string
Description string
}
//GetHoliday 取得休假日資料
func GetHoliday() []*Holiday {
list := []*Holiday{}
err := db.Db.Where("is_holiday = ?", 1).Find(&list).Error
if err != nil {
log.Fatal(err)
}
return list
}
......@@ -26,5 +26,6 @@ func API() *gin.Engine {
route.POST("/Redis/RPush", controllers.RPushRedis)
route.POST("/Redis/LSet", controllers.LSetRedis)
route.POST("/Redis/LRange", controllers.LRangeRedis)
route.POST("/PunchClock/CalcTime", controllers.CalcTime)
return route
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment