弹性工作制考勤统计

关于弹性工作制度的考勤统计

考核时间计算公式如下:
1、上午12点以前来的,中午会扣除1.5小时
2、超过19点下班的,会扣除1小时:
为什么要扣除1小时?健康是革命的本钱;督促大家去吃早餐
下午工作时间已经够久了,晚饭时间出去休息一下,适度休息,后续的工作效率会更高

同时计算是精确到分钟数的,19点以前下班,18点-19点之间的时间也是算在工作时间里

架构设计

数据结构

总的考勤Map[姓名]->用户->统计数组

程序设计
  • 考勤数据,csv格式
"189","XXX","技术研发中心","2017/9/14","09:29 23:00 23:01 23:01","2017/9/12"
  1. 把数据切割成多个字符串
  2. 取时间段的数据转换成时间对象
  3. 取第一个和最后一个时间取差

备注:花两小时写完的,没有考虑考勤跨天的情况

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")
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值