You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java自动化机器人中正确获取上月最后一天

问题:自动化机器人切换月份后无法正确获取上月最后一天

我开发的自动化机器人需要获取上月最后一天,当前月份首次运行时结果正常,但进入下一个月后,现有代码获取的日期出现错误。

问题代码片段:

Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -1);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
dateformat2 = new SimpleDateFormat((cal.get(Calendar.MONTH)+1)+"/"+cal.get(Calendar.DAY_OF_MONTH)+"/yyyy");

完整的Teco_Bot类代码:

import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class Teco_Bot extends Thread{
    WebDriver driver;
    GUI gui;
    String user[]= {"NorthVillage432","VPM1263"};
    String pass[]= {"user123","user123"};
    String accId[]= {"0","1"};
    SimpleDateFormat dateformat1,dateformatDay,dateformat2,dateformat3;
    Statement st;
    ResultSet rs;
    
    public Teco_Bot() {
        dateformat1 = new SimpleDateFormat("yyyy-MM-dd");
        dateformatDay = new SimpleDateFormat("dd");
        
        dateformat3 = new SimpleDateFormat("MM/dd/yyyy");
                Calendar cal = Calendar.getInstance();
            cal.add(Calendar.MONTH, -1);
            cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
            dateformat2 = new SimpleDateFormat((cal.get(Calendar.MONTH)+1)+"/"+cal.get(Calendar.DAY_OF_MONTH)+"/yyyy");
        gui = new GUI();
        
    }
    
    public void run() {
        
        String currentdate="";
        EmailNotification notif1;
        EmailNotification notif2;
        while(true) {
            try {
                Thread.sleep(2000);
            }catch(Exception ee) {ee.printStackTrace();}
            System.out.println("Waiting");
                    
            
            if((dateformatDay.format(new Date()).equalsIgnoreCase("05")||dateformatDay.format(new Date()).equalsIgnoreCase("15"))&&!currentdate.equalsIgnoreCase(dateformat1.format(new Date())))
            {
                 notif1 = new EmailNotification("junrybuenavista@yahoo.com",30,"Teco Bot");
                 notif1.start();
                 notif2 = new EmailNotification("michaelvinocur@htgrp.net",30,"Teco Bot");
                 notif2.start();
                setDataBaseConnection();
                        while(true) {
                            for(int i=0;i<user.length;i++) {
                                setBrowser();
                                gui.textAppend("Processing "+user[i]+"\n");
                                Login(user[i],pass[i]);
                                
                                currentdate = dateformat1.format(new Date());
                                try {
                                    st.execute("DELETE FROM `teco_data`");
                                }catch(Exception ee) {ee.printStackTrace();}
                                    
                                getData();
                                if(driver.findElements(By.xpath("//*[@id=\"selectionForm\"]/div[3]/div[2]/div[2]/ul/li[2]/a")).size() != 0) {
                                    driver.findElement(By.xpath("//*[@id=\"selectionForm\"]/div[3]/div[2]/div[2]/ul/li[2]/a")).click();
                                    System.out.println();   
                                    getData();
                                }
                                
                                
                                
                                driver.get("http://localhost/googleapi/teco-query.php?day="+dateformatDay.format(new Date())+"&acc="+accId[i]+"&date="+dateformat2.format(new Date())+"&date2="+dateformat3.format(new Date()));
                                System.out.println("http://localhost/googleapi/teco-query.php?day="+dateformatDay.format(new Date())+"&acc="+accId[i]+"&date="+dateformat2.format(new Date())+"&date2="+dateformat3.format(new Date()));
                                try {
                                    Thread.sleep(4000);
                                }catch(Exception ee) {ee.printStackTrace();}
                                driver.quit();
                                try {
                                    Thread.sleep(2000);
                                }catch(Exception ee) {ee.printStackTrace();}
                                gui.textAppend("Processing complete\n\n");
                                                                
                            }
                            try {
                                st.close();
                                rs.close();
                            }catch(Exception ee) {ee.printStackTrace();}
                            break;
                        }
                        notif1.setIsRunning(true);
                        notif2.setIsRunning(true);
                    }                                   
        }
    }
    public void getData() {
        try {
                
                WebElement table = driver.findElement(By.xpath("//*[@id=\"selectionForm\"]/div[2]/table"));
                List<WebElement> acc = table.findElements(By.xpath(".//tr/td[2]"));
                List<WebElement> add = table.findElements(By.xpath(".//tr/td[3]"));
                List<WebElement> amount_due = table.findElements(By.xpath(".//tr/td[4]"));
                List<WebElement> due_date = table.findElements(By.xpath(".//tr/td[5]"));
                
                for(int i=0;i<acc.size();i++) {             
                    System.out.print(acc.get(i).getText()+" ");
                    System.out.print(add.get(i).getText()+" ");
                    System.out.print(amount_due.get(i).getText()+" ");
                    System.out.println(due_date.get(i).getText()+" ");
                    st.execute("INSERT INTO teco_data (acc, address, amount_due, due_date)\r\n"
                            + "VALUES ('"+acc.get(i).getText()+"', '"+add.get(i).getText()+"', '"+amount_due.get(i).getText()+"', '"+due_date.get(i).getText()+"');");
                }
        }catch(Exception ee) {ee.printStackTrace();}        
    }
    public void setDataBaseConnection() {
        while(true) {
            System.out.println("Database connecting");
            gui.textAppend("Database connecting\n");
            try{  
                Thread.sleep(1500);
                Class.forName("com.mysql.jdbc.Driver");  
                Connection con=DriverManager.getConnection(  
                "jdbc:mysql://localhost:3306/teco_db","root","");   
                 st=con.createStatement();
                 break;
                
               }catch(Exception e){}
        }
    }
    public void setBrowser() {      
        System.setProperty("webdriver.chrome.driver", "C:\\Jars\\chromedriver.exe");        
        HashMap<String,Object> chromePrefs = new HashMap<String, Object>();
        chromePrefs.put("plugins.always_open_pdf_externally", true);
        chromePrefs.put("download.default_directory", "C:"+File.separator+"Square_download");
        chromePrefs.put("excludeSwitches", "enable-popup-blocking");    
        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("prefs", chromePrefs);
        
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);    
    }
    public void Login(String user,String pass) {

        gui.textAppend("Starting Login\n");
        driver.get("https://account.tecoenergy.com/");
        try {
            Thread.sleep(2000);
        }catch(Exception ee) {ee.printStackTrace();}
        driver.findElement(By.id("UserName")).sendKeys(user);
        driver.findElement(By.id("Credentials_Password")).sendKeys(pass);
        driver.findElement(By.id("login-submit")).click();
        gui.textAppend("Login complete\n");
        try {
            Thread.sleep(4000);
        }catch(Exception ee) {ee.printStackTrace();}
        
    }
    
    class GUI  
    {   JTextArea area;
    
         GUI(){  
                 area=new JTextArea();
                 area.setEditable(false);
                
                 
                 JScrollPane scrollableTextArea = new JScrollPane(area);
                   scrollableTextArea.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
                        public void adjustmentValueChanged(AdjustmentEvent e) {  
                            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
                        }
                    });
                 JFrame frame=new JFrame("Teco bot Running");
                 frame.add(scrollableTextArea);
                 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                 frame.setSize(500,300);
                 frame.setLocationRelativeTo(null);
                 frame.setVisible(true);
         }
         public void textAppend(String stringIn) {
             area.append(stringIn);
         }
         public void textClear() {
             area.setText("");
         }
    }
} 

问题分析

你的代码存在两个核心错误:

  1. 日期逻辑初始化时机错误:上月最后一天的计算和dateformat2的初始化写在构造函数里,只会在机器人启动时执行一次。月份切换后,不会重新计算,始终使用启动时的旧日期值。
  2. SimpleDateFormat用法错误:你把计算出的上月最后一天的具体月份、日期硬编码到了格式化字符串中,这完全违背了日期格式化的逻辑——SimpleDateFormat应该用固定格式(如MM/dd/yyyy)来格式化动态的日期对象,而非把日期值写进格式里。

解决方案

步骤1:重构构造函数,初始化固定格式的格式化器

把dateformat2改为固定格式,不再硬编码日期值:

public Teco_Bot() {
    dateformat1 = new SimpleDateFormat("yyyy-MM-dd");
    dateformatDay = new SimpleDateFormat("dd");
    dateformat2 = new SimpleDateFormat("MM/dd/yyyy"); // 固定格式,复用即可
    dateformat3 = new SimpleDateFormat("MM/dd/yyyy");
    gui = new GUI();
}

步骤2:在任务触发时实时计算上月最后一天

在run方法的任务逻辑中,每次需要使用上月最后一天时,实时计算并格式化:

// 替换原有URL拼接代码
// 实时计算上月最后一天
Calendar lastMonthCal = Calendar.getInstance();
lastMonthCal.add(Calendar.MONTH, -1);
lastMonthCal.set(Calendar.DAY_OF_MONTH, lastMonthCal.getActualMaximum(Calendar.DAY_OF_MONTH));
Date lastDayOfLastMonth = lastMonthCal.getTime();

// 格式化日期
String lastDayStr = dateformat2.format(lastDayOfLastMonth);
String currentDateStr = dateformat3.format(new Date());
String dayStr = dateformatDay.format(new Date());

// 拼接并访问URL
String url = "http://localhost/googleapi/teco-query.php?day=" + dayStr + "&acc=" + accId[i] + "&date=" + lastDayStr + "&date2=" + currentDateStr;
driver.get(url);
System.out.println(url);

更优方案:使用Java 8+的java.time API(推荐)

Calendar和SimpleDateFormat是旧API,存在线程不安全、设计繁琐等问题。推荐使用Java 8引入的java.time包,代码更简洁安全:

// 导入必要类
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

// 实时计算上月最后一天
LocalDate today = LocalDate.now();
LocalDate lastDayOfLastMonth = today.minusMonths(1).withDayOfMonth(today.minusMonths(1).lengthOfMonth());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String lastDayStr = lastDayOfLastMonth.format(formatter);

额外建议

  • 避免在循环中重复创建日期格式化器实例,可作为类成员变量复用。
  • Selenium中尽量用显式等待替代Thread.sleep(),提升代码稳定性。
  • 数据库操作存在SQL注入风险,建议使用PreparedStatement替代直接拼接SQL字符串。

内容的提问来源于stack exchange,提问作者Junry Buenavista

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:20:23