从CSV或txt格式的考勤记录中提取最早最晚打卡时间

参考资料:https://ask.csdn.net/questions/390993

测试数据:工号+姓名+打卡时间(只要打卡一次就记录一次时间)

测试文件格式:CSV或txt

12345,zhangsan,2018-12-05 01:57
12345,zhangsan,2018-12-05 01:57
12345,zhangsan,2018-12-05 01:58
12345,zhangsan,2018-12-05 01:58
12345,zhangsan,2018-12-05 01:59
1234,zhangsan,2018-12-05 01:59
12345,zhangsan,2018-12-05 02:02
12345,zhangsan,2018-12-05 02:02
12345,zhangsan,2018-12-05 02:03
12345,zhangsan,2018-12-05 02:03
1000,zhangsan,2018-12-05 02:04
1000,zhangsan,2018-12-05 02:05
1000,zhangsan,2018-12-05 02:05
1000,zhangsan,2018-12-05 02:05
1000,zhangsan,2018-12-05 02:06
1005,zhangsan,2018-12-05 02:06
1000,zhangsan,2018-12-05 02:06
1007,zhangsan,2018-12-05 02:07
1000,zhangsan,2018-12-05 02:17
1000,zhangsan,2018-12-05 02:17
1000,zhangsan,2018-12-05 02:18
1002,yang,2018-12-05 02:19
1002,yang,2018-12-05 02:19
1002,yang,2018-12-05 02:19
1002,yang,2018-12-05 02:20
1004,yang,2018-12-05 02:29
1002,yang,2018-12-05 02:30
1002,yang,2018-12-05 03:00
1002,yang,2018-12-05 03:01
1002,yang,2018-12-05 03:05
1004,yang,2018-12-05 03:05
12345,zhangsan,2018-12-05 02:03

代码实现:

效果:

第一步:输入考勤文件路径,如 c:\\2018-12-05.txt,返回结果list,此list内容格式如: 工号+姓名+最早打卡时间+最晚打卡时间。

第二部:将上述list写入CSV文件(可选操作)

Employee类

public class Employee implements Comparator<Employee> {
    //想直接利用List的API来排序,就要实现这个接口

    public String getStaffId() {
        return staffId;
    }

    public void setStaffId(String staffId) {
        this.staffId = staffId;
    }


    public String getCheckTime() {
        return checkTime;
    }

    public void setCheckTime(String checkTime) {
        this.checkTime = checkTime;
    }



    public String getStaffName() {
        return staffName;
    }

    public void setStaffName(String staffName) {
        this.staffName = staffName;
    }
    private String staffId;
    private String staffName;
    private String checkTime;
    //比较本对象和参数是否为同一天,这一个方法只是在一个打卡文件里有几天的打卡记录时才使用
    //但是一般一个文件对应一天的记录,所以本例中没有使用
    public boolean isSameDay(Employee attendance) {

        return this.checkTime.split(" ")[0].equals(attendance.getCheckTime().split(" ")[0]);
    }
    
    //按打卡时间排序的逻辑
    @Override
    public int compare(Employee employee, Employee t1) {
        Date date1 = null;
        Date date2 = null;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            date1 = formatter.parse(employee.getCheckTime());
            date2 = formatter.parse(t1.getCheckTime());
        } catch (ParseException e) {

            e.printStackTrace();
        }
        return (int) (date1.getTime() - date2.getTime());
    }

}
private static List<String> generateList(String csvPath) {
        List<String> resultList = new ArrayList<>(); //返回的结果
        Map<String, List<Employee>> map = new HashMap<>();
        List<Employee> employeeList = new ArrayList<>();  //这个list包含了全部的数据
        BufferedReader bufferedReader = null;
        //第一步:按行读取全部打卡CSV源数据到employeeList中
        try {
            bufferedReader = new BufferedReader(new FileReader(csvPath));
            String line = null;
            Employee employee;
            while ((line = bufferedReader.readLine()) != null) {
                String employeeData[] = line.split(",");
                employee = new Employee();
                employee.setStaffId(employeeData[0]);
                employee.setStaffName(employeeData[1]);
                employee.setCheckTime(employeeData[2]);
                employeeList.add(employee);
            }

            //第二步:遍历employeeList,不同的工号人员分类
            String staffId = "";
            for (Employee employee1 : employeeList) {
                staffId = employee1.getStaffId();
                employeeList = map.get(staffId); //根据工号找到其所有的打卡时间
                if (employeeList == null) {
                    employeeList = new ArrayList<>();
                }
                employeeList.add(employee1); //给该工号添加一条时间记录
                map.put(staffId, employeeList); //将该记录添加到map
            }

            //第三部:将map中的数据进行整理分析,排序打卡时间
            for (Map.Entry<String, List<Employee>> entry : map.entrySet()) {

                StringBuffer stringBuffer = new StringBuffer();
                employeeList = entry.getValue(); //一个员工的所有打卡时间列表
                employeeList.sort(new Employee()); //根据打卡时间排序,得到按时间从小到大的有序列表
                employee = employeeList.get(0);//得到第一个有序列表的第一个打卡时间(最早打卡时间)
                //得到最早的打卡时间(即排在第一个的节点)
                stringBuffer.append(employee.getStaffId() + "," + employee.getStaffName() + "," + employee.getCheckTime());
                //(遍历整个有序时间列表)得到最晚的打卡时间
                for (Employee employee1 : employeeList) {
                    //本例中下面的if不是必要的,因为一个文件对应一天的打卡记录
                     //只需要遍历到最后的日期就行
                    //如果一个CSV文件里面有不同的日期,才需要在这里面判断
//                    if (!employee.isSameDay(employee1)) {
//                        System.out.println(employee.getCheckTime().split(" ")[1]);
//                        System.out.print("员工号:" + employee1.getStaffId() + "\t" + employee1.getCheckTime().split(" ")[0] +
//                                "\t最早考勤时间:" + employee1.getCheckTime().split(" ")[1] + "\t最晚考勤时间:");
//                    }
                    //建议每天的打卡记录保存为不同的CSV文件
                    employee = employee1;
                }
                //System.out.println(employee.getCheckTime().split(" ")[1] + "\n");
                stringBuffer.append("," + employee.getCheckTime());
                resultList.add(stringBuffer.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
                map.clear();
                employeeList.clear();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultList;
    }

 上面的方法已经能得到结果了,以下的内容不是必须的。

目的:将上述的List结果写入CSV文件

 /**
     * 
     * @param list  上述方法返回的结果list
     * @param path  目标文件保存地址
     */
    private static void analyzeAndCreate(List<String> list, String path) {
        File file = new File(path);
        //如果是目录,记得mkdirs
        try {
            if (!file.exists())
                file.createNewFile();
            else
                file.delete();
            StringBuffer buffer;
            FileOutputStream outputStream = new FileOutputStream(file, true);
            buffer = new StringBuffer("工号,姓名,最早打卡时间,最晚打卡时间\r\n");
            outputStream.write(buffer.toString().getBytes("gbk"));
            for (String string : list) {
                buffer = new StringBuffer(string);
                buffer.append("\r\n");
                outputStream.write(buffer.toString().getBytes("gbk"));
            }
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

main函数

  public static void main(String[] args) {
        System.out.println("hello world");
        
        List<String> resultList = generateList("c:\\2018-12-05.csv"); //txt文件也行
        for (String s : resultList) {
            System.out.println(s);
        }
        analyzeAndCreate(resultList, "c:\\2018-12-05分析.csv");  //打开这个文件就看到了统计结果
    }

打开CSV文件:

点击查看Excel效果

注意:我是在Android 5.1下使用的上述java方法,但是报错(API 24及以上不会):java.lang.NoSuchMethodError: No interface method sort(Ljava/util/Comparator;),这是由employeeList.sort(new Employee());这一句引起的。

如果你遇到这个错误,解决办法之一:就是将employeeList.sort(new Employee());替换成

 Collections.sort(employeeList, new Comparator<Employee>() { //List排序
                    @Override
                    public int compare(Employee o1, Employee o2) {
                        Date date1 = null;
                        Date date2 = null;
                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        try {
                            date1 = formatter.parse(o1.getCheckTime());
                            date2 = formatter.parse(o2.getCheckTime());
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        return (int) (date1.getTime() - date2.getTime());
                    }
                });

参考链接:https://blog.csdn.net/qq_31371757/article/details/84837464

猜你喜欢

转载自blog.csdn.net/qq_31371757/article/details/84838476