Date类
Date类 实现Serializable Cloneable Comparable 接口
他的子类有:Date(sql包下的) Time Timestamp 这三个子类其实都是sql包下的
Date的构造方法:
Date() | 获取当前的时间对象 | |
Date(long date) | 将时间戳数字转化为Date类对象 | |
Date常用方法:
long getTime() | 将时间以long类型返回 |
boolean after(Date when) | 是否在指定时间之后 |
boolean before(Date when) | 是否在指定时间之前 |
Calendar日历类
用法比Date复杂,但是功能是日历,而不再需要我们进行long类型的加减操
常用方法:
Calendar getInstance() | 获取calendar的示例对象 |
int get(int field) | 获取calendar的成员日期或其他时间数据 |
set(int field, int value) | 设置指定成员的数据内容 |
abstract void add(int field, int amount) | 在指定的成员数据上进行加法运算 |
| |
public static void main(String[] args) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.MONTH, 6); //计算半年后的日期
instance.set(instance.get(Calendar.DAY_OF_MONTH), 3); // 设置这个月的第三天,即半年后的那个月的第三天
System.out.println(String.format("日历为,%s,%s,%s %s:%s:%s", instance.get(Calendar.YEAR)
, instance.get(Calendar.MONDAY)
, instance.get(Calendar.DAY_OF_MONTH)
, instance.get(Calendar.HOUR_OF_DAY)
, instance.get(Calendar.MINUTE)
, instance.get(Calendar.SECOND)
));
}
SimpleDateFormat:格式化日期类,在java.text 包下面,这个包是国际化都放在这个里面
这个类继承了DateFormat
format(Date date) | 将日期格式化转化为字符串 |
parse(String source) | 将字符串转化为日期 |
SimpleDateFormat(String pattern) | 创建对象,设置匹配模式 |
如果想成功的对日期进行格式化或者将字符串转化为日早起,那么 就必须存在有一个日期的匹配表达式,而这组表达式里面最重要的几个日期单位年(yyyy) 月(MM)日(dd)时(HH)分(mm)秒(ss)毫秒(SSS)
public static void main(String[] args) throws Exception{
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(dateFormat.format(date));
String str = "2020-04-01 22:23:11.606";
Date parse = dateFormat.parse(str);
System.out.println(parse);
}
java中常用的 数据类型和字符串相互转换的常用方法
LocalDate类
在jdk1.8 之后的版本里,java追加了一个新的日期时间的处理包,java.time ,在这个包有三个类比较重要LocalDate
LocalTime ,LocalDateTime ,通用Calendar类相比更加简单
public static void main(String[] args) throws Exception {
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("LocalDate 实例化输出" + localDate);
System.out.println("LocalTime 实例化输出" + localTime);
System.out.println("LocalDateTime 实例化输出" + localDateTime);
System.out.println(String.format("当前日期%s-%s-%s", localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth()));
System.out.println("获取一周的时间数" + localDate.getDayOfWeek().getValue());
System.out.println("今天所处的一月的周数" + localDate.get(ChronoField.ALIGNED_WEEK_OF_MONTH));
System.out.println("今天所处的一年的周数" + localDate.get(ChronoField.ALIGNED_WEEK_OF_YEAR));
System.out.println("今天所处的一年的第几天" + localDate.getDayOfYear());
LocalDate localDate2 = LocalDate.parse("2020-04-02");
System.out.println("是否是闰年" + localDate2.isLeapYear());
System.out.println("所在月的第一天" + localDate.with(TemporalAdjusters.firstDayOfMonth()));
System.out.println("所在月的第一天" + localDate.withDayOfMonth(1));
System.out.println("所在月的最后一天" + localDate.with(TemporalAdjusters.lastDayOfMonth()));
System.out.println("三百年后的日期" + localDate.plusYears(300));
System.out.println("日期所处月的第一个周一" + localDate.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)));
}
在多线程下的SimpleDateFormat类的操作:
首先说一下出现的原因:将字符串转化为日期,一定要使用SimpleDateFormat类,于是这个类成了所有项目开发中必然要采用的工具类,于是下面来针对这个工具类使用进行多线程环境下的分析:
单线程:
public static void main(String[] args) throws Exception{
for (int i = 0; i < 10; i++)
{
new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId() + sdf.parse("1998-02-17 22:31:32"));
} catch (ParseException e) {
e.printStackTrace();
}
}, "SDF转换线程" + i).start();
}
}
上述代代码,虽然也是多线程,但是每一个线程都保留了一个各自的SimpleDateFormat 类的对象,所以整个的转换是可以正常完成的,但是上述多个线程要将字符串转化为相同的类型的日期,所以没有必要每个线程都定义一个单独的SimpleDateFormat 类对象实例(这样可以减少内存垃圾内存开销)
所以我们可以修改代码(注意下面这代码是错误的,给大家演示现象,危险代码请勿模仿,这个错误时:将字符串转化为日期会报错,但是当日期转化为字符串时不会报错)
public static void main(String[] args) throws Exception{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (int i = 0; i < 10; i++)
{
new Thread(() -> {
try {
System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId() + sdf.parse("1998-02-17 22:31:32"));
} catch (ParseException e) {
e.printStackTrace();
}
}, "SDF转换线程" + i).start();
}
}
发现代码不仅报错,而且有的时间不对
为什么会报错:
出现的异常中有 NumberFormatException这个异常,是因为在设计SimpleDateFormat类的时候,它的转化处理操作机制并没有同步的处理,即线程A的日期时间传递过来之后,可能刚配置了一半数据之后,线程B又传过来的数据,也进行了匹配内容的变更,这样就会出现线程不同步的问题。
即多个线程不能并发的访问
如何解决这个问题的方法
1:传统方法,每个线程都有一个SimpleDateFormat 对象,就是我们最开始的那种方法,但是缺点就是造垃圾
2:我们利用jdk1.8 的LocalDate ,LocalDateTime LocalDateTime 类来完成
public static void main(String[] args) throws Exception{
// 创建日期的格式化类对象,定义SimpleDateFormat 类中的匹配日期时间字符串
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
ZoneId zoneId = ZoneId.systemDefault();
for (int i = 0; i < 10; i++)
{
new Thread(() -> {
try {
LocalDateTime localDateTime = LocalDateTime.parse("1998-02-17 22:31:32", formatter);
Instant instant = localDateTime.atZone(zoneId).toInstant();// 获得一个当前时区的一个实例
Date date = Date.from(instant);
System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId()+ date);
} catch (Exception e) {
e.printStackTrace();
}
}, "SDF转换线程" + i).start();
}
下面给出LocalDate 类
public static void main(String[] args) throws Exception{
// 创建日期的格式化类对象,定义SimpleDateFormat 类中的匹配日期时间字符串
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
ZoneId zoneId = ZoneId.systemDefault();
for (int i = 0; i < 10; i++)
{
new Thread(() -> {
try {
LocalDate localDate = LocalDate.parse("1998-02-17", formatter);
Instant instant = localDate.atStartOfDay().atZone(zoneId).toInstant();// 获得一个当前时区的一个实例
Date date = Date.from(instant);
System.out.println("当前线程的名称是:" + Thread.currentThread().getName()+ " 线程id是:" + Thread.currentThread().getId()+ date);
} catch (Exception e) {
e.printStackTrace();
}
}, "SDF转换线程" + i).start();
}
}