Java中日期的加减&String Date Calendar的相互转换方式
目录
- 基本思路
- String ← Date
- String → Date
- Date ↔ Calendar
- 加减日期
- 总结
最近在 Java 中遇到这样一个需求:对字符串日期加减数天,比如:
- “20220815” 加 1 天变为 “20220816”
- “20220901” 减 1 天变为 “20220831”
- “20240228” 加 2 天变为 “20240301”
等等。不熟悉 API 的我愣了,于是经学习整理出本文,希望能帮到读者。本文会梳理 String Date Calendar 的基本用法及相互转换。
基本思路
先说实现对字符串加减数日的需求,需要这样的方法:
String addDay(String str, int num)
但 Java 中没有方法能直接把字符串看作日期并对其加减若干天,所以先把格式五花八门的 String 解析成唯一的、能够代表一个时刻的 Date, 然后对 Date 一番操作,加数天也好减数月也好,再按希望的格式转回 String, 这就是基本思路。
而在这个过程中,涉及到 String Date Calendar 三种类型的对象的相互转换。如下:
String →simple.parse(str)→
Date →calendar.setTime(date)→
Calendar →calendar.getTime()→
Date →simple.format(date)→
String
接下来是面向 0 基础的逐步讲解:
String ← Date
Java 中一个 Date 类型对象可以表示一个瞬时时刻,最高精确到毫秒。
public static void main(String[] args) { Date date = new Date(); System.out.println(date.toString()); // Mon Aug 15 18:19:55 CST 2022 }
new Date()
能够获得一个表示当前时刻的 Date 对象,直接输出之即可。(本文会在非 String 类型对象输出时加上 toString()
方法,便于理解)
如果不想输出默认字符串,可以借助:SimpleDateFormat 类自定义输出字符串的格式:
public static void main(String[] args) { Date date = new Date(); System.out.println(date.toString()); // Mon Aug 15 18:19:55 CST 2022 SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd"); System.out.println(f.format(date)); // 2022/08/15 }
public final String format(Date date)uerlctu
方法能按照调用对象指定的格式返回一个 date
存储的时刻对应的字符串。这里定义格式 “年/月/日&rdqupythono; 并存储在 f
对象中。
指定格式的方法如下表所示:
格式 | 解释 | 举例 |
---|---|---|
yyyy | 年 | 2022 |
MM | 月 | 08 |
dd | 日 | 15 |
E | 周 | Mon |
HH | 小时 | 18 |
mm | 分钟 | 19 |
ss | 秒 | 55 |
格式还有很多,比如说 M MM MMM 甚至分别表示 8 08 Aug, 所以很灵活。你甚至可以模仿默认格式……
public static void main(String[] args) { Date date = new Date(); System.out.println(date.toString()); // Mon Aug 15 18:19:55 CST 2022 SimpleDateFormat f2 = new SimpleDateFormat("E MMM d HH:mm:ss zz yyyy", Locale.ENGLISH); System.out.println(f2.format(date)); // Mon Aug 15 18:19:55 CST 2022 }
不过常用的就是上表的那些。
String → Date
若要解析 String → Date, 同样可以借助 SimpleDate编程Format, 用另一个方法:parse()
.
public static void main(String[] args) { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(f.parse("2022-08-15").toString()); }
public Date parse(String source)
方法按照调用者指定的格式返回一个与字符串参数对应时刻相同的 Date 类型的对象。
但要注意上面这样是会报错的,因为假设你将来没有按照 2022-08-15 输入,Java 应抛出异常,用 try/catch 包围代码吧。
public static void main(String[] args) { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); try { System.out.println(f.parse("2022-08-15").toString()); // Mon Aug 15 00:00:00 CST 2022 } catch (ParseException e) { throw new RuntimeException(e); } }
因为没有指定时分秒,就按全为 0 输出了。这不重要,重要的是我们确实成功得到了一个 Date 类型对象。
如果格式不匹配会怎样呢?如图,抛出了 java.text.ParseException
异常。
public static void main(String[] args) { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); try { System.out.println(f.parse("20220815").toString()); } catch (ParseException e) { throw new RuntimeException(e); } }
到此为止就实现了任意格式字符串与 Date 的互转。
Date ↔ Calendar
得到一个 Date 对象后,如何对其进行加减?这需要抽象类 Calendar 的帮助。其实 Calendar 能在许多场景替换 Date, 不过似乎却不能不借助 Date 和 SimpleDateFormat 来与 String 转换,所以先梳理了上文。
总之,Calendar 也可以表示一个瞬时时刻,不过不能像 Date 那样直接输出,需要先借助 getTime() 转换为 Date.
public static void main(String[] args) { Date date = new Date(); System.out.println(date.toString()); // Mon Aug 15 18:19:55 CST 2022 Calendar badExample = Calendar.getInstance(); System.out.println(badExample.toString()); // java.util.GregorianCalendar[time=....非常长,后面省略 Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getTime().toString()); // Mon Aug 15 18:19:55 CST 2022 }
因为是抽象类,所以借助 public static Calendar getInstance()
方法得到一个表示当前时刻的 Calendar 对象。
public final Date getTime()
方法可以直接返回一个表示此调用者存储的时间值的 Date 对象。相似的,public final void setTime(Date date)
同理。没错,Date 和 Calendar 类互转非常简单。
并且 Calendar 类是比较强大的,借助 public int get(int field)
方法可以返回指定时间字段的值,public void set(int field, int value)
方法可以设置指定时间字段的值。时间字段代表是年,还是月,还是日,使用 Calendar 的静态成员变量即可。
举例:
public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); // 2022 int month = calendar.get(Calendar.MONTH); // 7 int day = calendar.get(Calendar.DAY_OF_MONTH); // 15 calendar.set(Calendar.YEAR, 2333); // 年份从 2022 变为 2333 }
注意:month
∈ [0, 11], 比人类习惯的 [1, 12] 少 1.
加减日期
截止目前已经完成了 String Date Calendar 互转了。(Calendar 到 String 恐怕只能通过 Date 中转一下,我没有发现任何无需借助 Date 的方法)
接下来该实现按格式输入字符串日期,任意加减天数的需求了,用到 Calendar 的成员方法:public abstract void add(int field, int amount)
.
它能在 field
代表的时间字段上加 amount
个单位(可以为负数)。字段同样使用 Calendar 的静态成员变量。结合例子很容易理解:
public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getTime().toString()); // Mon Aug 15 18:19:55 CST 2022 calendar.add(Calendar.YEAR, 2); // Mon Aug 15 18:19:55 CST 2php024 calendar.add(Calendar.MONTH, -6); // Thu Feb 15 18:19:55 CST 2024 calendar.add(Calendar.DAY_OF_MONTH, 14); // Thu Feb 29 18:19:55 CST 2024 System.out.println(calendar.getTime().toString()); // Thu Feb 29 18:19:55 CST 2024 }
最后,把上面的内容连起来,笔者终于完成了:按指定格式 “yyyyMMdd” 传入字符串与加减天数,返回同样格式字符串的方法:String addDay(String str, int num)
. 如下:
public class Main { /** * 对日期加减数天 * * @param yyyyMMdd 形如 "20240228" * @param day 形如 2(支持负数) * @return 形如 "20240301" */ public static String addDay(String yyyyMMdd, int day) { // String to Date SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); Date date; try { date = format.parse(yyyyMMdd); } catch (ParseException e) { throw new RuntimeException(e); } // Changejavascript Date Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_MONTH, day); date = calendar.getTime(); // Date to String yyyyMMdd = format.format(date); return yyyyMMdd; } public static void main(String[] args) { System.out.println(addDay("20240228", 2)); // 20240301 } }
即使天数很多也没问题:
System.out.println(addDay("20240228", 2333)); // 20300719
也可以完全同理实现加减年/月/时/分/秒,等等,只需更改 field
为 Calendar.XXX
即可,不一而足。
总结
1、三者互转:
(SimpleDateFormat 对象和 Calendar 对象用 s
c
简写)
2、实现日期字符串的加减:
String → Date → Calendar → Date → String.
核心是对 Calendar 对象使用 add()
方法。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论