日期计算器

一、 系统描述

完成日期计算器的编写。

系统功能:

1.输入日期,完成星期几的计算,并输出星期值

2.输入日期加天数,完成日期加/减天数的计算,并输出新日期

3.输入日期以及一个年月日,完成日期加/减该年月日的计算,并输出新 日期。

二、 实验要求和目的

1、理解并掌握图形界面的设计。
2、理解整体算法的思路,即actionPerformed()的算法。
3、输入日期,完成星期几的计算,并输出星期值(注意日期输入的合法性)
4、输入日期加天数,完成日期加天数的计算,并输出新日期(注意日期的合法输入,以及注意日期不能加日期,既第二次输入的只能是天数)
5、输入日期以及一个年月日,完成日期加/减该年月日的计算,并输出新日期。                                                               6、进一步学习JAVA的编程思想。

、 实验条件

编译器: Eclipse Java Oxygen

Java环境: JDK 1.8.0

操作系统: Windows 10 家庭中文版

、思路分析以及详细设计

布局管理程序(比如FlowLayout(流式布局)、BorderLayout(区域边框布局)、GridLayout(顺序依次排列))进行布局设计,同时限定了窗体的大小,防止用户无意改变窗口大小;

详细设计:

先利用FlowLayout设置用户界面上的屏幕组件的格式布局,然后使用BorderLayout将布局分为五个区域:北、南、东、西、中。利用GridLayout将中区域分割4*3,间隔10,10,用来存放数字按钮以及C和CE。东区域分割4*1,间隔10,10,用来存放+、-、/、=,北区域存放文本框。且将setResizable设为false表示生成的窗体大小是由程序员决定的,用户不可以自由改变该窗体的大小。

java 根据日期统计每月金额 java计算日期_文本框

        2. 封装了一个创建数字按钮的方法getNumberButton(int n),可以快速地进行增加数字按钮的操作; 

详细设计:

利用JButton库创建按钮,并设计函数为其添加事件。

"yyyy年MM月dd日是 E"的形式编写了toStringDate()方法,其中包括日期输入错误的异常处理。

详细设计:

先利用SimpleDateForma和parset把String:"yyyy/MM/dd" 类型转换成Date类型,再利用SimpleDateFormat的format,将Date类型转换为"yyyy年MM月dd日是 E"的形式。

为了区分日期加的天数还是年月日,编写了isNumber和isDate俩个函数去进行格式判断。

详细设计:

利用String的matches进行格式判断即可,数字格式:"\\d{0,}",年月日格式:"\\d{0,4}/([0-9]|1[0-2]|)/([0-9]|[1-2][0-9]|3[0-1])"即XXXX/XX/XX、/xx/xx或//xx.

编写了getDate函数。

详细设计:

逐个读取字符串于一个缓冲区内,当读取到‘/’或是结束时,则读出缓冲区,将其转为整形依次赋值给year,month,day,并清空缓冲区。若读出的缓冲区为空,赋值即为0。

6. 鼠标使用,定义了一个ButtonActionListener类使用了ActionListener接口然后覆写了actionPerformed,去实现按键监听对应的功能。

详细设计:

判断按钮若为"=",使用了bolean布尔型属性来标记是否为第一次出现等号即转化为 "yyyy年MM月dd日是 E"的形式,若不是第一次即执行加减功能。若为"+"、"-"则保存之前的时间,等到下一个等号计算。若为“CE”则清空文本框并复原bolean,若为“C”则删除文本框中的一个字符。

了一个KeyboardListener类使用了KeyListener接口然后覆写了keyReleased,去实现按键监听对应的功能。

详细设计:

判断键盘输入若为enter,使用了bolean布尔型属性来标记是否为第一次出现等号即转化为 "yyyy年MM月dd日是 E"的形式,若不是第一次即执行加减功能。若为"+"、"-"则保存之前的时间,等到下一个等号计算。若为Backspace则删除文本框中的一个字符。

        8.为实现+-操作、使用了isSymbol布尔型属性来标记当前状态,同时使用一个Calendar属性保存当前日期,在每步操作时都对其进行改变,最后=时输出。

详细设计:

定义一个全局变量isSymbol,遇到“+”时变为true,“-”时为false,然后遇到等号时去读取isSymbol判断执行加还是减。

  • 主要代码清单
package ll;



import java.awt.BorderLayout; //布置容器的边框布局,五个区域:北、南、东、西、中

import java.awt.Dimension; //封装了一个构件的高度和宽度

import java.awt.FlowLayout; //流式布局,组件按照加入的先后顺序按照设置的对齐方式从左向右排列,一行排满到下一行开始继续排列

import java.awt.GridLayout; //切割出来的版面就如同表格一般整齐,加入的组件会按顺序由左至右、由上至下摆放

import java.awt.event.ActionEvent; //按钮事件处理的一个接口

import java.awt.event.ActionListener; //用于接收按钮操作事件的侦听器接口

import java.awt.event.KeyEvent; //键盘事件处理的一个接口

import java.awt.event.KeyListener; //用于接收键盘操作事件的侦听器接口

import java.text.ParseException; //异常类

import java.text.SimpleDateFormat; //日期-时间格式化

import java.util.Calendar; //日期处理库

import java.util.Date; //日期库



import javax.swing.JButton; //按钮

import javax.swing.JFrame; //屏幕上window的对象,能够最大化、最小化、关闭。

import javax.swing.JPanel; //面板容器类

import javax.swing.JTextField; //轻量级组件,编辑单行文本



@SuppressWarnings("serial") //声明long类型的静态final serialVersionUID字段

public class Calculator extends JFrame{



JTextField textFile; //文本框

    Date date;

    String fullString; //全局(第一个时间)

    String before,after;

    Calendar calendar;// 全局变量用来保存时间

    int year = 0,month = 0,day = 0; // 全局变量用来保存年月日

    

    //bolean:确保第一次都是将日期转换成yyyy年MM月dd日是 E形式

    //isSymbol:判断符号是+还是-,true表示+

    //键盘监听事件keyLitener

    boolean bolean=true, isSymbol=true;

    int m;

    

public Calculator() {

JFrame jframe = new JFrame("日期计算机");

jframe.setLayout(new FlowLayout()); //设置用户界面上的屏幕组件的格式布局

jframe.setBounds(500, 150, 750, 350); //在屏幕左上角的焦点为0坐标,向右移动500个像素,向下移动150个像素,对话框宽为750个像素,高为350个像素。

textFile = new JTextField(50); //文本框长度为50列



        JPanel jpanel = new JPanel();

        jpanel.setLayout(new BorderLayout()); //布置容器的边框布局,五个区域:北、南、东、西、中

        JPanel jpanel_center = new JPanel(); //中区域

        jpanel_center.setLayout(new GridLayout(4, 3, 10, 10)); //中区域分割4*3,间隔10,10

        JPanel jpanel_north = new JPanel(); //北区域

        JPanel jpanel_east = new JPanel(); //东区域

        jpanel_east.setLayout(new GridLayout(4, 1, 10, 10));

        

        //北区域文本框

        jpanel_north.add(textFile);

        jpanel.add(jpanel_north, BorderLayout.NORTH);

        

        //中区域数字

        for (int i = 1; i < 10; i++) {

            jpanel_center.add(getNumberButton(i));

            

        }

        jpanel_center.add(getNumberButton("CE"));

        jpanel_center.add(getNumberButton(0));

        jpanel_center.add(getNumberButton("C"));

        jpanel.add(jpanel_center, BorderLayout.CENTER);

        

        //东区域符号

        jpanel_east.add(getNumberButton("+"));

        jpanel_east.add(getNumberButton("-"));

        jpanel_east.add(getNumberButton("/"));

        jpanel_east.add(getNumberButton("="));

        jpanel.add(jpanel_east, BorderLayout.EAST);



        jframe.add(jpanel);

        

        //文本框加入键盘监听

        KeyboardListener  kl = new KeyboardListener ();

        textFile.addKeyListener(kl);

        

        jframe.setResizable(false); //设置此窗体是否可由用户调整大小,false时,表示生成的窗体大小是由程序员决定的,用户不可以自由改变该窗体的大小

        jframe.setVisible(true); //数据模型已经构造好了,允许JVM可以根据数据模型执行paint方法开始画图并显示到屏幕上

}



    private JButton getNumberButton(int n) {

        JButton an = new JButton("" + n);

        //设置按钮的大小

        Dimension preferredSize = new Dimension(70, 55);

        an.setPreferredSize(preferredSize);

        ButtonActionListener  bl = new ButtonActionListener ();

        an.addActionListener(bl);

        return an;



    }

    private JButton getNumberButton(String n) {

     JButton an = new JButton("" + n);

     //设置按钮的大小

        Dimension preferredSize = new Dimension(70, 55);

        an.setPreferredSize(preferredSize);

        //监听

        ButtonActionListener  bl = new ButtonActionListener ();

        an.addActionListener(bl);

        return an;

    }

    

    public String toStringDate() {

        // 首先把String:"yyyy/MM/dd" 类型转换成Date类型

        SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd");

        String time= textFile.getText();

        try {

            date =f.parse(time);

        } catch (ParseException e) {

        

         textFile.setText("toStringDate异常");

        }

         

        String strDateFormat = "yyyy年MM月dd日是 E";

        SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);

        return sdf.format(date);

    }

    

    public boolean isNumber(String s){

     //判断是否为数字

        String r="\\d{0,}";

        return s.matches(r);

    }

    

    public boolean isDate(String s){

     //判断是否为年月日

     String r="\\d{0,4}/([0-9]|1[0-2]|)/([0-9]|[1-2][0-9]|3[0-1])"; //格式XXXX/XX/XX、/xx/xx、//xx.

     return s.matches(r);

    }

         

    public void getDate(String s) {

     //获取字符上的年月日

     int j = 1;

     String s1 = "";

     for(int i=0; i<s.length(); i++) {

     if(s.charAt(i)>=48 && s.charAt(i)<=57) {

     s1 += s.charAt(i);

     }

     if(s.charAt(i) == '/' || i == s.length()-1 ) {

     System.out.println(s1);

     if(s1 == "") s1 = "0"; //无数字即为0

     if(j == 1) {

         j++;

         year = Integer.parseInt(s1);

         s1 = "";

         }

     else if(j == 2) {

         j++;

         month = Integer.parseInt(s1);

         s1 = "";

         }

         else if(j == 3) {

         j++;

         day = Integer.parseInt(s1);

         s1 = "";

         }

     }

     }

    }

    

    public Calendar toDate(String s) throws Exception {

        SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");

        Date d = df.parse(s); //解析一个日期时间字符串,并返回 1970/1/1 午夜距离该日期时间的毫秒数

        Calendar cal = Calendar.getInstance(); //单例模式创建Calendar类的实例,在主函数开始时调用,返回一个实例化对象,此对象是static的.

        cal.setTime(d); //以毫秒设置 Date 对象,据 GMT 时间 1970 年 1 月 1 日午夜之间的毫秒数

        return cal;

    }

    

    class ButtonActionListener   implements ActionListener {

public void actionPerformed(ActionEvent e) {

// TODO Auto-generated method stub

if(e.getActionCommand().equals("=")) {

after=fullString;



if(bolean){ //第一个=必须转换日期格式

                    System.out.println("第一次发现等号,执行转换成日期格式");

                    after=textFile.getText();

                    System.out.println(after);

                    String regex="\\d{1,4}/([1-9]|1[0-2])/([1-9]|[1-2][0-9]|3[0-1])"; //格式XXXX/XX/XX,前面为空即是0,每个至少一位

                    System.out.println(after.matches(regex));

                    if(after.matches(regex)){ //格式判断

                        try {

                            textFile.setText(toStringDate());

                        } catch (Exception e1) {

                         textFile.setText("toStringDate()抛出异常!!!");

                        }

                    }

                    else{

                     textFile.setText("输入与日期格式不匹配");

                    }

                    bolean=false;

                }

else { //非第一个=,日期计算



if(isNumber(after)) {

m = Integer.parseInt(after); //数字部分,天数操作

if(isSymbol){ //这里还要判断是+还是-,对日进行操作

calendar.add(Calendar.DATE, m);        

                    }else{

                     calendar.add(Calendar.DATE, -m);

                    }



SimpleDateFormat sj=new SimpleDateFormat("yyyy/MM/dd");

fullString=sj.format(calendar.getTime());

System.out.println(fullString);



 try { //

date =sj.parse(fullString);

String strDateFormat = "yyyy年MM月dd日是 E";

                    SimpleDateFormat s = new SimpleDateFormat(strDateFormat);

                    textFile.setText(s.format(date));

} catch (ParseException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

else if(isDate(after)) { //天数操作,年月日

getDate(after);



if(isSymbol){ //这里还要判断是+还是-,对日进行操作

calendar.add(Calendar.DATE, day);

calendar.add(Calendar.MONTH, month);

calendar.add(Calendar.YEAR, year);

                    }

else{

                     calendar.add(Calendar.DATE, -day);

                     calendar.add(Calendar.MONTH, -month);

                     calendar.add(Calendar.YEAR, -year);

                    }



SimpleDateFormat sj=new SimpleDateFormat("yyyy/MM/dd");

fullString=sj.format(calendar.getTime());

System.out.println(fullString);



 try { //

date =sj.parse(fullString);

String strDateFormat = "yyyy年MM月dd日是 E";

                    SimpleDateFormat s = new SimpleDateFormat(strDateFormat);

                    textFile.setText(s.format(date));

} catch (ParseException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}



}

else {

textFile.setText("输入格式不正确");

}

}



}



else if(e.getActionCommand().equals("+")) {

isSymbol=true;

before = fullString; //用来存储加号前面的数据



try {

calendar=toDate(before);

} catch (Exception e1) {

// TODO Auto-generated catch block

textFile.setText("toDate错误");

}

System.out.println("实现+");

textFile.setText("");

}

else if(e.getActionCommand().equals("-")) {

isSymbol=false;

before = fullString; //用来存储加号前面的数据



try {

calendar=toDate(before);

} catch (Exception e1) {

// TODO Auto-generated catch block

textFile.setText("toDate错误");

}

System.out.println("实现-");

textFile.setText("");

}

else if(e.getActionCommand().equals("CE")) {

System.out.println("实现CE");

textFile.setText("");

                bolean=true;

 }

else if(e.getActionCommand().equals("C")) {

System.out.println("实现C");

fullString = fullString.substring(0, fullString.length()-1);

textFile.setText(fullString);

}

            else{

                textFile.setText(textFile.getText()+e.getActionCommand());

                fullString=textFile.getText(); //边按边存入全局变量

            }

}



    }

    

    class KeyboardListener implements KeyListener{



public void keyTyped(KeyEvent e) {

// TODO Auto-generated method stub



}



public void keyPressed(KeyEvent e) {

// TODO Auto-generated method stub

}



public void keyReleased(KeyEvent e) {

// TODO Auto-generated method stub

if(e.getKeyChar() == KeyEvent.VK_ENTER) {

after=fullString;



if(bolean){ //第一个=必须转换日期格式

                    System.out.println("第一次发现等号,执行转换成日期格式");

                    after=textFile.getText();

                    System.out.println(after);

                    String regex="\\d{1,4}/([1-9]|1[0-2])/([1-9]|[1-2][0-9]|3[0-1])"; //格式XXXX/XX/XX,前面为空即是0,每个至少一位

                    System.out.println(after.matches(regex));

                    if(after.matches(regex)){ //格式判断

                        try {

                            textFile.setText(toStringDate());

                        } catch (Exception e1) {

                         textFile.setText("toStringDate()抛出异常!!!");

                        }

                    }

                    else{

                     textFile.setText("输入与日期格式不匹配");

                    }

                    bolean=false;

                }

else { //非第一个=,日期计算



if(isNumber(after)) {

m = Integer.parseInt(after); //数字部分,天数操作

if(isSymbol){ //这里还要判断是+还是-,对日进行操作

calendar.add(Calendar.DATE, m);        

                    }else{

                     calendar.add(Calendar.DATE, -m);

                    }



SimpleDateFormat sj=new SimpleDateFormat("yyyy/MM/dd");

fullString=sj.format(calendar.getTime());

System.out.println(fullString);



 try { //

date =sj.parse(fullString);

String strDateFormat = "yyyy年MM月dd日是 E";

                    SimpleDateFormat s = new SimpleDateFormat(strDateFormat);

                    textFile.setText(s.format(date));

} catch (ParseException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

else if(isDate(after)) { //天数操作,年月日

getDate(after);



if(isSymbol){ //这里还要判断是+还是-,对日进行操作

calendar.add(Calendar.DATE, day);

calendar.add(Calendar.MONTH, month);

calendar.add(Calendar.YEAR, year);

                    }

else{

                     calendar.add(Calendar.DATE, -day);

                     calendar.add(Calendar.MONTH, -month);

                     calendar.add(Calendar.YEAR, -year);

                    }



SimpleDateFormat sj=new SimpleDateFormat("yyyy/MM/dd");

fullString=sj.format(calendar.getTime());

System.out.println(fullString);



 try { //

date =sj.parse(fullString);

String strDateFormat = "yyyy年MM月dd日是 E";

                    SimpleDateFormat s = new SimpleDateFormat(strDateFormat);

                    textFile.setText(s.format(date));

} catch (ParseException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}



}

else {

textFile.setText("输入格式不正确");

}

}



}



else if(e.getKeyChar() == '+') {

isSymbol=true;

before = fullString; //用来存储加号前面的数据



try {

calendar=toDate(before);

} catch (Exception e1) {

// TODO Auto-generated catch block

textFile.setText("toDate错误");

}

System.out.println("实现+");

textFile.setText("");

}

else if(e.getKeyChar() == '-') {

isSymbol=false;

before = fullString; //用来存储加号前面的数据



try {

calendar=toDate(before);

} catch (Exception e1) {

// TODO Auto-generated catch block

textFile.setText("toDate错误");

}

System.out.println("实现-");

textFile.setText("");

}

else if(e.getKeyChar() == KeyEvent.VK_BACK_SPACE) {

System.out.println("实现C");

fullString=textFile.getText();

}

            else{

                textFile.setText(textFile.getText());

                fullString=textFile.getText(); //边按边存入全局变量

            }

}

    

    }

    

public static void main(String[] args) {

// TODO Auto-generated method stub

new Calculator();



}

}
  •  调试与运行情况

java 根据日期统计每月金额 java计算日期_java_02

加20天

java 根据日期统计每月金额 java计算日期_java_03

 

java 根据日期统计每月金额 java计算日期_java_04

减30天

java 根据日期统计每月金额 java计算日期_文本框_05

java 根据日期统计每月金额 java计算日期_java_06

加上两年两月两日

java 根据日期统计每月金额 java计算日期_java_07

 

java 根据日期统计每月金额 java计算日期_java 根据日期统计每月金额_08

、 实验小结

系统设计的功能基本都完成了实现,该系统尽可能的模拟现实的情况,使得系统设计更加贴近于现实情况。但也存在一些问题,例如如果经过减操作之后的日期是公元前的日期,结果依然会显示为公元年份。使用时也需要按一定要求输入,需要先输入一个日期,按下等于号后,才能进行加减,并且不能连加,连减。还有键盘输入时,一定要注意必须是英文输入法。