在Java中,不建议直接自定义Date类,因为java.util.Date和java.util.Calendar类已经提供了处理日期和时间的基本功能,可以使用SimpleDateFormat类格式化日期(较常用的方式)等。
这里将自定义封装一个Date类,用于日期对象的创建和格式化,作为一个刚入门的练习案例。
一、创建Date对象
在src目录中创建工具类包com.project.utils,并在里面新建一个Date对象类文件,代码如下:
package com.project.utils;
import java.util.Calendar;
/*
* 日期类
*/
public class Date {
}
二、定义属性
在一个日期中,有年、月、日、时、分、秒、周几等相关属性值,这里将它们全部定义为私有的,类的属性定义为私有是面向对象编程中的一个重要实践,它体现了封装性、信息隐藏、控制访问、实现代码模块化和遵循面向对象设计原则等思想和原则。
代码如下:
package com.project.utils;
import java.util.Calendar;
/*
* 日期类
*/
public class Date {
private int year; // 年
private int month; // 月
private int day; // 日
private int hour; // 小时
private int minute; // 分
private int second; // 秒
private char week; // 周几
private final String WEEK_STR = "日一二三四五六";
}
这里定义了一个常量WEEK_STR,是用于将日期中对应星期的数值转换为汉字,索引0为星期日,故“日”要放在第一位。
三、构造函数定义
此案例中将定义两种构造函数(即构造函数重载):一是无参构造函数,用于创建默认的当前时日期时间(由于java.util.Date中方法已废弃,这里使用java.util.Calendar实例和方法);二是有参构造函数,用于创建指定的日期时间(这里作为案例演示,不过多重载了)。
Calendar类相关属性和方法,可查看文档了解,地址:Calendar (Java 2 Platform SE 6)
代码如下:
package com.project.utils;
import java.util.Calendar;
/*
* 日期类
*/
public class Date {
private int year;
private int month;
private int day;
private int hour;
private int minute;
private int second;
private char week;
private final String WEEK_STR = "日一二三四五六";
/**
* 无参构造函数
*/
public Date(){
Calendar date = Calendar.getInstance();
this.year = date.get(Calendar.YEAR);
this.month = date.get(Calendar.MONTH);
this.day = date.get(Calendar.DATE);
this.hour = date.get(Calendar.HOUR_OF_DAY);
this.minute = date.get(Calendar.MINUTE);
this.second = date.get(Calendar.SECOND);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 有参构造函数
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
*/
public Date(int year, int month, int day, int hour, int minute, int second){
this.year = year;
this.month = month-1;
this.day = day;
this.hour = hour;
this.minute = minute;
this.second = second;
// 获取当前是周几
Calendar date = Calendar.getInstance();
date.set(year, this.month, this.day, this.hour, this.minute, this.second);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
}
注意的是,常量WEEK_STR是按照java.util.Date的实例方法getDay()来定义的,索引值是从0到6;但是java.util.Calendar的date.get(Calendar.DAY_OF_WEEK)获取的索引是从1到7,所以需要减1处理。
四、校验参数合法性
当通过有参构造函数实例对象时,传入的值如果不合法,将会造成程序无法正常运行下,或出现异常等问题。所以将定义一些校验参数合法性的功能函数,在有参构造函数赋值时调用,如果不合法将其设置为0。
代码如下:
package com.project.utils;
import java.util.Calendar;
/*
* 日期类
*/
public class Date {
private int year;
private int month;
private int day;
private int hour;
private int minute;
private int second;
private char week;
private final String WEEK_STR = "日一二三四五六";
/**
* 无参构造函数
*/
public Date(){
Calendar date = Calendar.getInstance();
this.year = date.get(Calendar.YEAR);
this.month = date.get(Calendar.MONTH);
this.day = date.get(Calendar.DATE);
this.hour = date.get(Calendar.HOUR_OF_DAY);
this.minute = date.get(Calendar.MINUTE);
this.second = date.get(Calendar.SECOND);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 有参构造函数
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
*/
public Date(int year, int month, int day, int hour, int minute, int second){
this.year = year;
this.month = isMonth(month-1);
this.day = isDay(day);
this.hour = isHours(hour);
this.minute = isMinuteOfSecond(minute);
this.second = isMinuteOfSecond(second);
// 获取当前是周几
Calendar date = Calendar.getInstance();
date.set(year, this.month, this.day, this.hour, this.minute, this.second);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 检测月份的合法性
* @param month
* @return
*/
private int isMonth(int month){
if(month >= 1 && month <= 12) return month;
else {
System.out.println("Invalid month (" + month + ") set to 0.");
return 0;
}
}
/**
* 检测日的合法性
* @param day
* @return
*/
private int isDay(int day){
int monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if(day >= 1 && day <= monthDays[month]) return day;
else {
System.out.println("Invalid month (" + day + ") set to 0.");
return 0;
}
}
/**
* 检测小时的合法性
* @param hour
* @return
*/
private int isHours(int hour){
if(hour >= 0 && hour < 24) return hour;
else{
System.out.println("Invalid month (" + hour + ") set to 0.");
return 0;
}
}
/**
* 检测分钟和秒数的合法性
* @param value
* @return
*/
private int isMinuteOfSecond(int value){
if(value >= 0 && value < 60) return value;
else{
System.out.println("Invalid month (" + value + ") set to 0.");
return 0;
}
}
}
五、格式化日期
Java中其实已有相关日期格式化类,如java.text.SimpleDateFormat,不过这里我们将通过replaceAll()方法自定义规则,来格式化输出日期。
代码如下:
package com.project.utils;
import java.util.Calendar;
/*
* 日期类
*/
public class Date {
private int year;
private int month;
private int day;
private int hour;
private int minute;
private int second;
private char week;
private final String WEEK_STR = "日一二三四五六";
/**
* 无参构造函数
*/
public Date(){
Calendar date = Calendar.getInstance();
this.year = date.get(Calendar.YEAR);
this.month = date.get(Calendar.MONTH);
this.day = date.get(Calendar.DATE);
this.hour = date.get(Calendar.HOUR_OF_DAY);
this.minute = date.get(Calendar.MINUTE);
this.second = date.get(Calendar.SECOND);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 有参构造函数
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
*/
public Date(int year, int month, int day, int hour, int minute, int second){
this.year = year;
this.month = isMonth(month-1);
this.day = isDay(day);
this.hour = isHours(hour);
this.minute = isMinuteOfSecond(minute);
this.second = isMinuteOfSecond(second);
// 获取当前是周几
Calendar date = Calendar.getInstance();
date.set(year, this.month, this.day, this.hour, this.minute, this.second);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 输出日期为字符串
* @param format
* @return
*/
public String dateFormatToString(String format){
format = format.replaceAll("YYYY", "" + year);
format = format.replaceAll("MM", "" + (month+1));
format = format.replaceAll("DD", "" + day);
format = format.replaceAll("hh", "" + hour);
format = format.replaceAll("ii", "" + minute);
format = format.replaceAll("ss", "" + second);
format = format.replaceAll("WW", "" + week);
return format;
}
/**
* 检测月份的合法性
* @param month
* @return
*/
private int isMonth(int month){
if(month >= 1 && month <= 12) return month;
else {
System.out.println("Invalid month (" + month + ") set to 0.");
return 0;
}
}
/**
* 检测日的合法性
* @param day
* @return
*/
private int isDay(int day){
int monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if(day >= 1 && day <= monthDays[month]) return day;
else {
System.out.println("Invalid month (" + day + ") set to 0.");
return 0;
}
}
/**
* 检测小时的合法性
* @param hour
* @return
*/
private int isHours(int hour){
if(hour >= 0 && hour < 24) return hour;
else{
System.out.println("Invalid month (" + hour + ") set to 0.");
return 0;
}
}
/**
* 检测分钟和秒数的合法性
* @param value
* @return
*/
private int isMinuteOfSecond(int value){
if(value >= 0 && value < 60) return value;
else{
System.out.println("Invalid month (" + value + ") set to 0.");
return 0;
}
}
}
六、实例
日期类已经定义好了,现在我们在新建一个java文件,将它引入进来并实例日期对象,输出我们需要的内容。
代码如下:
package com.project;
import com.project.utils;
/**
* Test类
*/
public class TestDate {
public static void main(String[] args) {
Date date = new Date();
String dateStr = date.dateFormatToString("YYYY/MM/DD hh:ii:ss 星期WW");
System.out.println(dateStr);
System.out.println(date.dateFormatToString("今天是YYYY年MM月DD日 hh时ii分ss秒星期WW"));
Date date2 = new Date(2024, 5, 26, 10, 44, 30);
String dateStr2 = date2.dateFormatToString("YYYY/MM/DD hh:ii:ss 星期WW");
System.out.println(dateStr2);
}
}
输出结果如下图:
七、优化
com.project.utils.Date类中的dateFormatToString(String format)方法体写了大量重复性代码,这里将使用HashMap键值对方式存储格式化数据,并通过迭代器循环输出。
代码如下:
/**
* 输出日期为字符串
* @param format
* @return
*/
public String dateFormatToString(String format){
Map<String, String> map = new HashMap<>();
// 追加对应key和value
map.put("YYYY", "" + year);
map.put("MM", ""+(month+1));
map.put("DD", ""+day);
map.put("hh", ""+hour);
map.put("ii", ""+minute);
map.put("ss", ""+second);
map.put("WW", ""+week);
// 循环输出
for(Map.Entry<String, String> entry: map.entrySet()){
format = format.replaceAll(entry.getKey(), entry.getValue());
}
return format;
}
此时再次执行运行结果和前面是一样的,如果需要增加规则,直接使用map.put()追加即可(如hour需要输出为24小时,还是12小时,或者小于10的数值是否要在前面补0等)。
八、get和set
对象的属性通常会被声明为私有(private)的,这是为了封装对象的内部状态,防止外部代码直接访问和修改这些状态,从而确保对象的不变性和安全性。为了实现对私有属性的访问和修改,我们通常会为这些属性提供公共的(public)getter和setter方法。
此时我们将年、月、日、时、分、秒等私有属性提供公共的setter和getter方法,并对setter的值进行合法性校验。代码如下:
package com.project.utils;
import java.util.Calendar;
/*
* 日期类
*/
public class Date {
private int year;
private int month;
private int day;
private int hour;
private int minute;
private int second;
private char week;
private final String WEEK_STR = "日一二三四五六";
/**
* 无参构造函数
*/
public Date(){
Calendar date = Calendar.getInstance();
this.year = date.get(Calendar.YEAR);
this.month = date.get(Calendar.MONTH);
this.day = date.get(Calendar.DATE);
this.hour = date.get(Calendar.HOUR_OF_DAY);
this.minute = date.get(Calendar.MINUTE);
this.second = date.get(Calendar.SECOND);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 有参构造函数
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
*/
public Date(int year, int month, int day, int hour, int minute, int second){
this.year = year;
this.month = isMonth(month-1);
this.day = isDay(day);
this.hour = isHours(hour);
this.minute = isMinuteOfSecond(minute);
this.second = isMinuteOfSecond(second);
// 获取当前是周几
Calendar date = Calendar.getInstance();
date.set(year, this.month, this.day, this.hour, this.minute, this.second);
this.week = WEEK_STR.charAt(date.get(Calendar.DAY_OF_WEEK) - 1);
}
/**
* 输出日期为字符串
* @param format
* @return
*/
public String dateFormatToString(String format){
Map<String, String> map = new HashMap<>();
// 追加对应key和value
map.put("YYYY", "" + year);
map.put("MM", ""+(month+1));
map.put("DD", ""+day);
map.put("hh", ""+hour);
map.put("ii", ""+minute);
map.put("ss", ""+second);
map.put("WW", ""+week);
// 循环输出
for(Map.Entry<String, String> entry: map.entrySet()){
format = format.replaceAll(entry.getKey(), entry.getValue());
}
return format;
}
/**
* 检测月份的合法性
* @param month
* @return
*/
private int isMonth(int month){
if(month >= 1 && month <= 12) return month;
else {
System.out.println("Invalid month (" + month + ") set to 0.");
return 0;
}
}
/**
* 检测日的合法性
* @param day
* @return
*/
private int isDay(int day){
int monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if(day >= 1 && day <= monthDays[month]) return day;
else {
System.out.println("Invalid month (" + day + ") set to 0.");
return 0;
}
}
/**
* 检测小时的合法性
* @param hour
* @return
*/
private int isHours(int hour){
if(hour >= 0 && hour < 24) return hour;
else{
System.out.println("Invalid month (" + hour + ") set to 0.");
return 0;
}
}
/**
* 检测分钟和秒数的合法性
* @param value
* @return
*/
private int isMinuteOfSecond(int value){
if(value >= 0 && value < 60) return value;
else{
System.out.println("Invalid month (" + value + ") set to 0.");
return 0;
}
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = isMonth(month);
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = isDay(day);
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = isHours(hour);
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = isMinuteOfSecond(minute);
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = isMinuteOfSecond(second);
}
}
这里就先讲到这,希望对大家有所帮助!