关于弹性工作制度的考勤统计
考核时间计算公式如下:
1、上午12点以前来的,中午会扣除1.5小时
2、超过19点下班的,会扣除1小时:
为什么要扣除1小时?健康是革命的本钱;督促大家去吃早餐
下午工作时间已经够久了,晚饭时间出去休息一下,适度休息,后续的工作效率会更高
同时计算是精确到分钟数的,19点以前下班,18点-19点之间的时间也是算在工作时间里
总的考勤Map[姓名]->用户->统计数组
"189","XXX","技术研发中心","2017/9/14","09:29 23:00 23:01 23:01","2017/9/12"
备注:花两小时写完的,没有考虑考勤跨天的情况
package main
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strings"
"time"
"github.com/axgle/mahonia"
)
type daytime struct {
day string
work float64
desc string
t string
}
type worktime struct {
name string
date []daytime
total float64
}
var TimeStatics map[string]worktime
//Mon, 15 Jan 2006 15:04:05 GMT
func calWorkTime(t string) (error, float64) {
tnew := strings.Replace(t, "\"", "", -1)
//fmt.Println("new time:", tnew)
tt := strings.Split(tnew, " ")
if len(tt) < 2 {
fmt.Println("考勤异常")
return errors.New("wrong"), 0
}
fmt.Println("new times:", tt)
n := len(tt)
T1, _ := time.Parse("15:04", tt[0])
T2, _ := time.Parse("15:04", tt[n-1])
T := T2.Sub(T1)
res := T.Hours()
//12点前打卡,减去午休时长
T0, _ := time.Parse("15:04", "12:00")
if T0.Unix() > T1.Unix() {
fmt.Println("calWorkTime: 减去午休时间:", res)
res = T.Hours() - 1.5
}
//晚上减去晚饭时间
T0, _ = time.Parse("15:04", "19:00")
if T0.Unix() < T2.Unix() {
fmt.Println("calWorkTime: 减去晚餐时间:", res)
res -= 1
}
fmt.Println("calWorkTime: 打卡时间", res)
fmt.Println("时间差:", T.Hours())
return nil, res
}
//gbk utf-8 格式转换
func ConvertToString(src string, srcCode string, tagCode string) string {
srcCoder := mahonia.NewDecoder(srcCode)
srcResult := srcCoder.ConvertString(src)
tagCoder := mahonia.NewDecoder(tagCode)
_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
result := string(cdata)
return result
}
func parseValue(input string) {
line := ConvertToString(input, "gbk", "utf-8")
//fmt.Println("value:", line)
v := strings.Split(line, ",")
fmt.Println("value:", v)
if len(v[4]) < 1 {
//fmt.Println("缺少考勤", v[1], v[3])
addoneday(v[1], 0, v[3], "缺少考勤", v[3])
return
}
err, times := calWorkTime(v[4])
if err != nil {
addoneday(v[1], times, v[3], "缺少考勤", v[4])
} else {
addoneday(v[1], times, v[3], "正常", v[4])
}
}
//考勤全部加到一个数组中
func addoneday(name string, t float64, date string, desc string, ts string) {
var daystatic worktime
if v, ok := TimeStatics[name]; ok {
daystatic = v
} else {
daystatic = worktime{name, make([]daytime, 0), 0}
}
daystatic.date = append(daystatic.date, daytime{date, t, desc, ts})
daystatic.total += t
TimeStatics[name] = daystatic
}
func showallData(result map[string]worktime) {
f, err := os.Create("./output.csv")
defer f.Close()
if err != nil {
panic(err)
}
w := bufio.NewWriter(f)
fmt.Fprintf(w, "\"日期\",\"打卡记录\",\"打卡时长\",\"描述\"\n")
for k, v := range result {
fmt.Printf("\n %s :考勤时长: %.2f\n", k, v.total)
fmt.Fprintf(w, "%s,\"%s\",\"%.2f\",\"%s\"\n", k, "考勤总时长", v.total, "")
for _, v1 := range v.date {
fmt.Printf("日期:%s,打卡:%s,工作时长:%.2f,描述:%s\n", v1.day, v1.t, v1.work, v1.desc)
fmt.Fprintf(w, "%s,%s,\"%.2f\",\"%s\"\n", v1.day, v1.t, v1.work, v1.desc)
}
}
w.Flush()
f.Sync()
}
func ReadLine(fileName string) error {
f, err := os.Open(fileName)
if err != nil {
return err
}
TimeStatics = make(map[string]worktime)
buf := bufio.NewReader(f)
buf.ReadString('\n')
for {
line, err := buf.ReadString('\n')
if err != nil {
if err == io.EOF {
showallData(TimeStatics)
return nil
}
return err
}
line = strings.TrimSpace(line)
//if strings.Contains(line, "技术研发中心") {
parseValue(line)
//}
}
return nil
}
func main() {
ReadLine("./InOutData.csv")
}