![](/img/trans.png)
[英]JXDatePicker using SimpleDateFormat to format dd.MM.yy to dd.MM.yyyy with current century
[英]What is the best way to parse a date in MM/DD/YY format and adjust it to the current / previous century?
我们的一位客户希望能够输入年份部分只有 2 位数字的日期。 日期将是过去的日期,因此如果 2 位数年份晚于当前年份,我们希望它适用于上个世纪,但如果 2 位数年份等于或小于当前年份,则它适用于当前世纪。
截至今天 10/30/2008
01/01/01 = 01/01/2001
01/01/09 = 01/01/1909
这是一个奇怪的要求,我解决了这个问题,我只是不喜欢我的解决方案。 感觉有更好的方法可以做到这一点。
谢谢您的帮助。
public static String stupidDate(String dateString)
{
String twoDigitYear = StringUtils.right(dateString, 2);
String newDate = StringUtils.left(dateString, dateString.length() - 2);
int year = NumberUtils.toInt(twoDigitYear);
Calendar c = GregorianCalendar.getInstance();
int centuryInt = c.get(Calendar.YEAR) - year;
newDate = newDate + StringUtils.left(Integer.toString(centuryInt), 2) + twoDigitYear;
return newDate;
}
Groovy脚本(很容易引入java)演示@bobince关于SimpleDateFormat的观点。
import java.text.SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat('MM/dd/yy')
SimpleDateFormat fmt = new SimpleDateFormat('yyyy-MM-dd')
Calendar cal = Calendar.getInstance()
cal.add(Calendar.YEAR, -100)
sdf.set2DigitYearStart(cal.getTime())
dates = ['01/01/01', '10/30/08','01/01/09']
dates.each {String d ->
println fmt.format(sdf.parse(d))
}
产量
2001-01-01
2008-10-30
1909-01-01
SimpleDateFormat已经为您使用两个字母的“yy”格式进行了两位数的年份解析。 (显然它仍然允许四位数。)
默认情况下,它使用now-80→now + 20,因此它与你提出的规则不完全相同,但它是合理的和标准化的(至少在Java世界中),并且如果你愿意,可以使用set2DigitYearStart()覆盖它。
DateFormat informat= new SimpleDateFormat("MM/dd/yy");
DateFormat outformat= new SimpleDateFormat("MM/dd/yyyy");
return outformat.format(informat.parse(dateString));
从长远来看,尝试迁移到ISO8601日期格式(yyyy-MM-dd),因为MM / dd / yy大约是最糟糕的日期格式,并且最终会导致问题。
这个怎么样:
public static String anEasierStupidDateWithNoStringParsing(String dateString) {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
//handling ParseExceptions is an exercise left to the reader!
Date date = df.parse(dateString);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
Calendar now = Calendar.getInstance();
if (cal.after(now)) {
cal.add(Calendar.YEAR, -100);
}
return cal;
}
换句话说,如果SimpleDateFormat( 它有自己的解释年份字符串的规则 )返回当前日期之后的日期,让SimpleDateFormat解析String并将年份调整为上个世纪。
这样可以保证返回的所有日期都是过去的。 但是,它没有说明在上个世纪之前可能被解析的任何日期 - 例如,格式为MM/dd/yyyy
,日期字符串如“01/11/12”解析为公元12年1月11日
如果Joda Time是一个选项:
String inputDate = "01/01/08";
// assuming U.S. style date, since it's not clear from your original question
DateTimeFormatter parser = DateTimeFormat.forPattern("MM/dd/yy");
DateTime dateTime = parser.parseDateTime(inputDate);
// if after current time
if (dateTime.isAfter(new DateTime())) {
dateTime = dateTime.minus(Years.ONE);
}
return dateTime.toString("MM/dd/yyyy");
我知道Joda Time不是Java SE的一部分,正如我在另一个帖子中所说的那样,当有一个Java库做同样的事情时,我通常不会宽恕使用第三方库。 然而,正在开发Joda Time的人也在领导JSR310--日期和时间API,它将进入Java 7.所以我Joda Time基本上将在未来的Java版本中。
接受的答案使用遗留日期时间 API,这是 2008 年提出问题时的正确做法。 2014 年 3 月, java.time
API 取代了容易出错的遗留日期时间 API 。 从那时起,强烈建议使用这个现代日期时间 API。
DateTimeFormatterBuilder#optionalStart
和DateTimeFormatterBuilder#optionalEnd
之间放置可选模式,并创建一个格式化程序,它可以解析具有四位数年份或两位数年份的日期字符串。DateTimeFormatterBuilder#appendValueReduced
,您可以根据需要指定年份的基值。演示:
import java.time.LocalDate;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
DateTimeFormatter parser = new DateTimeFormatterBuilder()
.appendPattern("M/d/")
.optionalStart()
.appendPattern("uuuu")
.optionalEnd()
.optionalStart()
.appendValueReduced(ChronoField.YEAR, 2, 2, Year.now().minusYears(100).getValue())
.optionalEnd()
.toFormatter(Locale.ENGLISH);
// Test
Stream.of(
"1/2/2022",
"01/2/2022",
"1/02/2022",
"01/02/2022",
"1/2/22",
"1/2/21",
"1/2/20",
"1/2/23",
"1/2/24"
)
.map(s -> LocalDate.parse(s, parser))
.forEach(System.out::println);
}
}
Output :
2022-01-02
2022-01-02
2022-01-02
2022-01-02
1922-01-02
2021-01-02
2020-01-02
1923-01-02
1924-01-02
请注意,年份大于当前年份的两位数的日期将被解析为具有上个世纪的LocalDate
。
您可以在 java-util-date 实例上使用Date#toInstant
从旧日期时间切换到现代日期时间 API。 一旦你有了一个Instant
,你就可以很容易地获得其他日期时间类型java.time
API。一个Instant
代表一个时刻并且独立于时区,即它代表一个 UTC 日期时间(通常显示为Z
代表祖鲁时间并且ZoneOffset
为+00:00
)。
演示:
public class Main {
public static void main(String[] args) {
Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant);
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Kolkata"));
System.out.println(zdt);
OffsetDateTime odt = instant.atOffset(ZoneOffset.of("+05:30"));
System.out.println(odt);
// Alternatively, using time-zone
odt = instant.atZone(ZoneId.of("Asia/Kolkata")).toOffsetDateTime();
System.out.println(odt);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Kolkata"));
System.out.println(ldt);
// Alternatively,
ldt = instant.atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime();
System.out.println(ldt);
}
}
Output :
2022-11-20T20:32:42.823Z
2022-11-21T02:02:42.823+05:30[Asia/Kolkata]
2022-11-21T02:02:42.823+05:30
2022-11-21T02:02:42.823+05:30
2022-11-21T02:02:42.823
2022-11-21T02:02:42.823
从Trail:Date Time了解有关现代日期时间 API 的更多信息。
Date deliverDate = new SimpleDateFormat("MM/dd/yy").parse(deliverDateString);
String dateString2 = new SimpleDateFormat("yyyy-MM-dd").format(deliverDate);
为我工作
优秀的Joda-Time 2.5库包含此功能。 无需自己编写任何代码。 只需在DateTimeFormatter
上调用withPivotYear()
。 有关如何使用它的示例,请参阅该链接文档。
最好的方法是在Java中使用Joda Time API来表示日期和时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.