Convert java.util.Date to java.time.LocalDate
将
简短的回答
1 2 |
说明
尽管它的名字,
JSR-310中
1 2 3 |
1 2 3 4 |
Java 9回答
在Java SE 9中,添加了一种新方法,可以略微简化此任务:
1 2 |
这种新的替代方案更直接,产生更少的垃圾,因此应该表现更好。
更好的方法是:
1 2 |
这个版本的优点:
-
无论输入是
java.util.Date 的实例还是它的子类java.sql.Date (不像@ JodaStephen的方式)都可以工作。这在JDBC源数据中很常见。java.sql.Date.toInstant() 总是抛出异常。 -
对于带有JSR-310反向端口的JDK8和JDK7,它也是一样的
我个人使用实用程序类(但这不是与backport兼容):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | /** * Utilities for conversion between the old and new JDK date types * (between {@code java.util.Date} and {@code java.time.*}). * * <p> * All methods are null-safe. */ public class DateConvertUtils { /** * Calls {@link #asLocalDate(Date, ZoneId)} with the system default time zone. */ public static LocalDate asLocalDate(java.util.Date date) { return asLocalDate(date, ZoneId.systemDefault()); } /** * Creates {@link LocalDate} from {@code java.util.Date} or it's subclasses. Null-safe. */ public static LocalDate asLocalDate(java.util.Date date, ZoneId zone) { if (date == null) return null; if (date instanceof java.sql.Date) return ((java.sql.Date) date).toLocalDate(); else return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDate(); } /** * Calls {@link #asLocalDateTime(Date, ZoneId)} with the system default time zone. */ public static LocalDateTime asLocalDateTime(java.util.Date date) { return asLocalDateTime(date, ZoneId.systemDefault()); } /** * Creates {@link LocalDateTime} from {@code java.util.Date} or it's subclasses. Null-safe. */ public static LocalDateTime asLocalDateTime(java.util.Date date, ZoneId zone) { if (date == null) return null; if (date instanceof java.sql.Timestamp) return ((java.sql.Timestamp) date).toLocalDateTime(); else return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDateTime(); } /** * Calls {@link #asUtilDate(Object, ZoneId)} with the system default time zone. */ public static java.util.Date asUtilDate(Object date) { return asUtilDate(date, ZoneId.systemDefault()); } /** * Creates a {@link java.util.Date} from various date objects. Is null-safe. Currently supports: <ul> * <li> {@link java.util.Date} * <li> {@link java.sql.Date} * <li> {@link java.sql.Timestamp} * <li> {@link java.time.LocalDate} * <li> {@link java.time.LocalDateTime} * <li> {@link java.time.ZonedDateTime} * <li> {@link java.time.Instant} * </ul> * * @param zone Time zone, used only if the input object is LocalDate or LocalDateTime. * * @return {@link java.util.Date} (exactly this class, not a subclass, such as java.sql.Date) */ public static java.util.Date asUtilDate(Object date, ZoneId zone) { if (date == null) return null; if (date instanceof java.sql.Date || date instanceof java.sql.Timestamp) return new java.util.Date(((java.util.Date) date).getTime()); if (date instanceof java.util.Date) return (java.util.Date) date; if (date instanceof LocalDate) return java.util.Date.from(((LocalDate) date).atStartOfDay(zone).toInstant()); if (date instanceof LocalDateTime) return java.util.Date.from(((LocalDateTime) date).atZone(zone).toInstant()); if (date instanceof ZonedDateTime) return java.util.Date.from(((ZonedDateTime) date).toInstant()); if (date instanceof Instant) return java.util.Date.from((Instant) date); throw new UnsupportedOperationException("Don't know hot to convert" + date.getClass().getName() +" to java.util.Date"); } /** * Creates an {@link Instant} from {@code java.util.Date} or it's subclasses. Null-safe. */ public static Instant asInstant(Date date) { if (date == null) return null; else return Instant.ofEpochMilli(date.getTime()); } /** * Calls {@link #asZonedDateTime(Date, ZoneId)} with the system default time zone. */ public static ZonedDateTime asZonedDateTime(Date date) { return asZonedDateTime(date, ZoneId.systemDefault()); } /** * Creates {@link ZonedDateTime} from {@code java.util.Date} or it's subclasses. Null-safe. */ public static ZonedDateTime asZonedDateTime(Date date, ZoneId zone) { if (date == null) return null; else return asInstant(date).atZone(zone); } } |
这里的
1 |
如果您使用的是Java 8,@ JodaStephen的答案显然是最好的。但是,如果您正在使用JSR-310 backport,那么很遗憾,您必须执行以下操作:
1 2 3 4 5 6 |
您可以在一行中转换:
1 2 3 | public static LocalDate getLocalDateFromDate(Date date){ return LocalDate.from(Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault())); } |
首先,很容易将日期转换为即时
1 |
然后,您可以使用ofInstant()方法将Instant转换为jdk 8中的任何日期api:
1 | LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault()); |
1 2 3 |
1 2 | public static LocalDate Date2LocalDate(Date date) { return LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy")) |
此格式来自
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public String toString() { //"EEE MMM dd HH:mm:ss zzz yyyy"; BaseCalendar.Date date = normalize(); StringBuilder sb = new StringBuilder(28); int index = date.getDayOfWeek(); if (index == BaseCalendar.SUNDAY) { index = 8; } convertToAbbr(sb, wtb[index]).append(' '); // EEE convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss TimeZone zi = date.getZone(); if (zi != null) { sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz } else { sb.append("GMT"); } sb.append(' ').append(date.getYear()); // yyyy return sb.toString(); } |
这1条简单的线路有什么问题?
1 |
@JodaStephen在JBoss EAP 6上的实现遇到了问题。因此,我在http://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html上重写了Oracle Java教程之后的转换。
1 2 3 4 5 | Date input = new Date(); GregorianCalendar gregorianCalendar = (GregorianCalendar) Calendar.getInstance(); gregorianCalendar.setTime(input); ZonedDateTime zonedDateTime = gregorianCalendar.toZonedDateTime(); zonedDateTime.toLocalDate(); |
我用以下解决方案解决了这个问题
1 2 3 4 5 |
在这种情况下,localDate以"yyyy-MM-dd"格式打印您的日期