1、日期和时间表示
Date是老的用于处理日期和时间的类,现在只建议对其进行时间戳转换的使用:
import java.util.Calendar;
import java.util.Date;
public class Test
{
public static void main(String[] args)
throws Exception
{
Date date1 = new Date(); //获得当前日期时间
long times = System.currentTimeMillis(); //获得当前毫秒级别的unix时间戳
long l = date1.getTime(); //获得对应的毫秒级的unix时间戳
Date date2 = new Date(times); //传入一个毫秒级的unix时间戳
}
}
TimeZone表示时区:
import java.util.*;
public class Test
{
public static void main(String[] args)
{
//
TimeZone zone = TimeZone.getDefault(); //获得当前默认时区
String str = zone.getDisplayName(); //"中国标准时间"
str = zone.getID(); //"Asia/Shanghai"
int dst = zone.getDSTSavings(); //夏令时数:0
TimeZone zone2 = TimeZone.getTimeZone("Asia/Taipei"); //获得台湾时区
String[] ary = TimeZone.getAvailableIDs(); //获得所有时区的ID
}
}
LocalDateTime、Instant等是新的处理时间的类,它们是线程安全的,推荐使用。对于LocalDateTime,如果设定了不存在的日期,如LocalDateTime.of(2018, 2, 29, 12, 3, 3)会抛出DateTimeException,因为2018年不是闰年,所以对于用户设置日期的功能,为了避免用户设定不存咋的时间,我们应该提供一个日期时间选择器(Date Time Picker)组件,而不是直接让用户输入时间。
import java.time.*;
import java.time.temporal.ChronoField;
public class Test
{
public static void main(String[] args)
{
//LocalDateTime:表示本地日期时间
LocalDateTime dt = LocalDateTime.now(); //获得本机当前日期时间
String str = "" + dt; //2018-06-14T10:47:56.231352700
long d = dt.getYear(); //获得年,同 lldd1.getLong(ChronoField.YEAR);
d = dt.getMonthValue(); //12, 获得月份,同 lldd1.getLong(ChronoField.MONTH_OF_YEAR);
d = dt.getDayOfMonth(); //获得日,同lldd1.getLong(ChronoField.DAY_OF_MONTH)
d = dt.getDayOfWeek().getValue(); //获得星期几,同 lldd1.getLong(ChronoField.DAY_OF_WEEK);
d = dt.getDayOfYear(); //获得一年中的第几天,同lldd1.getLong(ChronoField.DAY_OF_YEAR)
LocalDateTime dt2 = dt.plusDays(5)
.plusHours(3)
.plusMinutes(10); //增加5天3小时10分钟
d = dt2.getLong(ChronoField.EPOCH_DAY/*1970到现在的天数*/) - dt.getLong(ChronoField.EPOCH_DAY); //5
long h = dt2.getLong(ChronoField.HOUR_OF_DAY/*0-23*/) - dt.getLong(ChronoField.HOUR_OF_DAY); //3
long m = dt2.getLong(ChronoField.MINUTE_OF_HOUR/*0-59*/) - dt.getLong(ChronoField.MINUTE_OF_HOUR); //10
long seconds = dt2.toInstant(ZoneOffset.of("+8")).getEpochSecond() -
dt.toInstant(ZoneOffset.of("+8")).getEpochSecond(); //dt2和dt1总共相差的秒数
//LocalDateTime LocalDateTime::plus(long amountToAdd, TemporalUnit unit)
//ChronoUnit是TemporalUnit接口的实现类,并且是一个Enum枚举类
LocalDateTime lldd2 = LocalDateTime.of(1999, 10, 1, 8, 5, 20).plus(5, ChronoUnit.DAYS) //增加5天
.plus(1, ChronoUnit.MONTHS); //增加1个月
LocalDateTime dt3 = LocalDateTime.of(2020, 2, 1, 13, 35, 10); //2020年2月1号13点35分10秒
str = "" + dt; //2020-02-1T13:35:10
int hour = dt3.getHour(); //13
LocalDateTime dt4 = dt3.withDayOfMonth(2); //获得一个新的日期时间,重新设置了日,2020年2月2号13点35分10秒
int nDays = dt4.getDayOfYear(); // 33
long second = dt3.toEpochSecond(ZoneOffset.of("+8")); //LocalDateTime转时间戳(秒)
long milliSecond = dt3.toInstant(ZoneOffset.of("+8")).toEpochMilli(); //LocalDateTime转时间戳(毫秒)
LocalDateTime ldt = LocalDateTime.ofEpochSecond(second/*秒*/, 500 * 1000 * 1000/*纳秒*/, ZoneOffset.of("+8")); //时间戳(秒+纳秒)转LocalDateTime
System.out.println("" + ldt); //2020-12-11T13:24:17.500
//获得本机当前毫秒级别的unix时间戳
long ti = System.currentTimeMillis();
//LocalDate:表示本地日期
LocalDate ld = LocalDate.now(); //获取当前日期
str = "" + ld; //2018-06-14
LocalDate ld3 = LocalDate.of(2014, Month.MAY, 21); //设为2014年5月21号
LocalDate ld2 = LocalDate.ofYearDay(2014, 146); //获取2014年的第146天
//LocalTime:表示本地时间
LocalTime lt = LocalTime.now(); //获取当前时间
str = "" + lt; //10:43:29.463094400
lt = LocalTime.of(10, 30); //设为10点30分
lt = LocalTime.ofSecondOfDay(5000); //获得一天中的第5000秒的时间
LocalDateTime localDT = LocalDateTime.of(ld, lt);
}
import java.time.*;
import java.time.temporal.ChronoField;
public class Test
{
public static void main(String[] args)
{
//Instant:表示一个UTC时间
Instant it = Instant.now(); //获得的是当前UTC时间而不是本地时间
String str = "" + it; //2020-12-10T08:49:14.112409200Z
Instant it2 = Instant.parse("2014-02-23T13:12:35.341Z");
str = "" + it2; //2014-02-23T13:12:35.341Z
long tim = it2.getEpochSecond(); //Instant转时间戳,这里的时间戳加了8小时,也就是是本地时间2014-02-23 21:12:35.341对应的时间戳,如下所示:
LocalDateTime dt = LocalDateTime.ofEpochSecond(tim, 0, ZoneOffset.of("+8"));
str = "" + dt; //2014-02-23T21:12:35
Instant inst = Instant.ofEpochSecond(tim); //时间戳转Instant,这里的时间戳使用了上面本地时间对应的时间戳,但转成Instant的话还是原来的UTC时间,所下所示:
str = "" + inst; //2014-02-23T13:12:35Z
ZonedDateTime zdt = it2.atZone(ZoneId.systemDefault()); //Instant转换为本地时间ZonedDateTime
str = "" + zdt; //2014-02-23T21:12:35.341+08:00[Asia/Shanghai]
LocalDateTime localDT = LocalDateTime.now();
Instant ins = localDT.toInstant(ZoneOffset.of("+8")); //LocalDateTime转Instant
LocalDateTime localNewDT = LocalDateTime.ofInstant(ins, ZoneId.of("+8")); //Instant转LocalDateTime
}
}
import java.time.*;
public class Test
{
public static void main(String[] args)
{
//YearMonth、MonthDay、Year分别表示年月、月日、年、月
Year year = Year.now(); //获取当前年份
String str = "" + year; //2018
year = year.plusYears(10); //年份再加上10年
YearMonth ym = year.atMonth(10); //月份设为10月
ym = ym.plusYears(2).plusMonths(5); //加上2年5个月
YearMonth ym1 = YearMonth.now();
System.out.println(ym1); // 2020-12
YearMonth ym2 = ym1.plus(1, ChronoUnit.MONTHS);
System.out.println("" + ym2); // 2021-01
//MonthDay不存在plus()、minus()方法(只实现了TemporalAccessor,plus()、minus()是TemporalAccessor的子接口Temporal上的方法),因为MonthDay不存在年的信息,如果是2月28号再加1天的话不确定是2月29还是3月1日
MonthDay md = MonthDay.now(); //获取当前月日
str = "" + md; //--06-14
md.with(Month.MAY).withDayOfMonth(23); //设为5月23日
for(Month month : Month.values())
{
System.out.printf("%d\t%s, ", month.getValue(), month);
//输出为 1 JANUARY, 2 FEBRUARY, 3 MARCH, ...
}
//Clock:获取指定时区的现在时间
Clock clock = Clock.systemUTC(); //获得UTC时间
System.out.println("" + clock); // SystemClock[Z]
Clock clo = Clock.systemDefaultZone();
System.out.println("" + clo); // SystemClock[Asia/Shanghai]
//Duration:表示一段时间
Duration du = Duration.ofSeconds(7200); //7200秒的时间段
long l = du.toMinutes(); //120,7200秒是120分钟
long h = du.toHours(); //2,7200秒是2小时
Clock clock2 = Clock.offset(clock, du); //在clock的基础上增加7200秒
//Period表示日期间隔,如果想要表示比日更小的单位应该使用Duration
LocalDate ld1 = LocalDate.of(1975, 5, 25).plus(Period.ofDays(5)) //加5天
.plus(Period.ofMonths(1)); //加1个月
LocalDate ld2 = LocalDate.now();
Period per = Period.between(ld1, ld2); //两个日期的间隔值
int y = per.getYears();
int m = per.getMonths();
int d = per.getDays();
System.out.printf("两个日期相差了%d年 %d个月, %d天", y, m, d); //两个日期相差了45年 5个月, 11天
}
}
Calendar是一个抽象日历类,GregorianCalendar是其子类,表示公历,也可以通过实现Calendar来实现其它的历法,如农历(网上有对农历的实现)。
import java.util.Calendar;
import java.util.Date;
public class Test
{
public static void main(String[] args)
{
Calendar calendar1 = Calendar.getInstance(); //使用默认的TimeZone和Locale获取GregorianCalendar对象
//Calendar calendar2 = Calendar.getInstance(TimeZone.getTimeZone("Europe/Copenhagen")); //获得哥本哈根的日历对象
Date date = calendar1.getTime(); //通过Calendar获得Date
Calendar calendar2 = Calendar.getInstance();
calendar2.setTime(date); //通过Date设置Calendar
boolean b = calendar2.after(calendar1); //判断日期前后
Calendar calendar3 = Calendar.getInstance();
calendar3.set(2000, 10, 1, 10, 0, 0); //设置年月日时分秒
int day = calendar1.get(Calendar.DATE); //获得日,从1开始
calendar1.add(Calendar.DATE, 1); //日加1,如果超过日期的最大会自动进位,如果不想进位的话使用roll()
calendar1.add(calendar.MONTH, 1); //月加1
calendar1.set(Calendar.MONTH, 11); //设置月份为12,月份从0开始,设置的数字超过范围的话会向前进位,不想自动进位的话调用setLenient()进行设置
//Calendar的set()具有延时性,直到再次调用get()或add()等方法的时候才会重新设置当前的时间
Calendar calendar4 = Calendar.getInstance();
calendar4.set(2000, 4, 31);
calendar4.set(Calendar.MONTH, 8); //设置月份为9,但9月31号不存在,将变为2000-10-1
calendar4.set(Calendar.DATE, 5);
Date d = calendar4.getTime(); //2000-9-5
}
}
夏令时:
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Calendar cal = Calendar.getInstance();
cal.set(1975, Calendar.MARCH, 31, 23, 59, 59); // 1975年3月31号23点59分59秒
cal.add(Calendar.SECOND, 1); //增加1秒
Date d = cal.getTime(); //当前是中国的话是1975年4月1号0点0分0秒,如果当前是实行夏令时的地区的话为1975年4月1号1点0分0秒
}
}
2、格式化
DateFormat、SimpleDateFormat是老的用来对日期和时间进行格式化的类:
import java.util.Date;
import java.text.*;
public class Test
{
public static void main(String[] args)throws ParseException
{
Date dNow = new Date( );
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss:SS");
String str = "当前时间为: " + ft.format(dNow); //当前时间为: 2020-09-29 15:25:20:962
String strTime = "2010##三月#21";
SimpleDateFormat ft2 = new SimpleDateFormat("y##MMM#d");
Date d = ft2.parse(strTime);
str = "" + d; // Sun Mar 21 00:00:00 CST 2010
}
}
还可以使用printf、String.format()来格式化日期,模式通过"%t"加下面表格的字符来控制:
import java.util.Date;
public class Test
{
public static void main(String[] args)
throws Exception
{
LocalDateTime dt = LocalDateTime.now();
String s = String.format("%tF", dt) + " " + String.format("%tT", dt);
System.out.println(s); //2020-12-11 14:41:03
}
}
java8中增加了功能更强大的DateTimeFormatter类,而且它是线程安全的,推荐使用:
import java.time.*;
import java.time.format.*;
public class Test
{
public static void main(String[] args)
{
//格式化字符串
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 E a HH:mm:ss:SSS");
String str = date.format(formatter); //等价于formatter.format(date),2018年06月15日 周五 下午 16:31:05:452
//解析字符串
str = "2014-04-12 01时06分23秒";
formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH时mm分ss秒");
date = LocalDateTime.parse(str, formatter);
str = "" + date; //2014-04-12T01:06:23
//格式化字符串
String strIns = Instant.ofEpochMilli(System.currentTimeMillis()).atZone(ZoneId.systemDefault())
.format(DateTimeFormatter.ISO_INSTANT); //"2023-10-30T08:51:09.574Z"
//解析字符串
Instant ist = Instant.parse(strIns);
strIns = "" + ist; //"2023-10-30T08:51:09.574Z"
}
}