对于wwSimpleDateFormat的奇怪行为感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍奇怪的英文weird,并为您提供关于Android棉花糖中的SimpleDateFormat行为
对于ww SimpleDateFormat的奇怪行为感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍奇怪的英文weird,并为您提供关于Android棉花糖中的SimpleDateFormat行为更改、DateFormat 类和 SimpleDateFormat 类、DateTimeFormatter与SimpleDateFormat、DateTimeFormatter和SimpleDateFormat有什么区别?的有用信息。
本文目录一览:- ww SimpleDateFormat的奇怪行为(奇怪的英文weird)
- Android棉花糖中的SimpleDateFormat行为更改
- DateFormat 类和 SimpleDateFormat 类
- DateTimeFormatter与SimpleDateFormat
- DateTimeFormatter和SimpleDateFormat有什么区别?
ww SimpleDateFormat的奇怪行为(奇怪的英文weird)
谁能解释为什么我在尝试解析日期时会得到这些值?我尝试了三种不同的输入,如下所示:
1)2013年第三周
Date date = new SimpleDateFormat("ww.yyyy").parse("02.2013");Calendar cal = Calendar.getInstance();cal.setTime(date);System.out.println(cal.get(Calendar.WEEK_OF_YEAR) + "." + cal.get(Calendar.YEAR));
哪个输出:(02.2013
正如我预期的那样)
2)2013年第一周
Date date = new SimpleDateFormat("ww.yyyy").parse("00.2013");Calendar cal = Calendar.getInstance();cal.setTime(date);System.out.println(cal.get(Calendar.WEEK_OF_YEAR) + "." + cal.get(Calendar.YEAR));
哪个输出:(52.2012
对我来说很好,因为2013年的第一周也是2012年的最后一个)
3)2013年第二周
Date date = new SimpleDateFormat("ww.yyyy").parse("01.2013");Calendar cal = Calendar.getInstance();cal.setTime(date);System.out.println(cal.get(Calendar.WEEK_OF_YEAR) + "." + cal.get(Calendar.YEAR));
哪个输出:(1.2012
这对我来说绝对 没有 意义)
有谁知道为什么会这样吗?我需要解析格式为(一年中的一周)。(年)的日期。我使用的是错误的模式吗?
答案1
小编典典您正在使用ww
,它是“一周的年”,然后yyyy
是“日历年”而不是“周年”。设置星期几,然后设置日历年是解决问题的秘诀,因为它们实际上只是单独的编号系统。
您应该YYYY
在格式字符串中使用它来指定星期年份…尽管不幸的是,看起来您无法以一种理智的方式 获取
该值。(我期望一个Calendar.WEEKYEAR
常数,但是没有这样的东西。)
同样,一年中的周值从1开始,而不是0 …并且两周中没有周。它 无论是 2013年的第一个星期 或者
是2012年的最后一个星期......这不是两个。
如果可以的话,我个人会避免使用周年和周-它们可能会非常令人困惑,尤其是当一个日历年中的日期在另一个周年中时。
Android棉花糖中的SimpleDateFormat行为更改
我在Android
6.0(棉花糖)上遇到了日期格式问题。引发以下异常的代码是我的应用程序用于API请求(“客户端”)的纯Java库(单独构建)。如果相关的话,该库是用Java
1.6构建的……无论如何,这是代码。
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd E hh:mm aa", Locale.UK);Date eventDate = dateFormat.parse(StringUtils.substring(record, 0, 23).trim());
… record
具有价值;
2015-10-23 Fri 10:59 PM BST 3.60 meters
…“修剪”之后是;
2015-10-23 Fri 10:59 PMyyyy-MM-dd E hh:mm aa
该代码自Froyo成立以来一直有效,并且已经过单元测试。除了棉花糖,所有东西都会抛出异常。
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: SynchroniseTidePosition.doInBackground10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: java.text.ParseException: Unparseable date: "2015-10-23 Fri 10:59 PM" (at offset 21)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at java.text.DateFormat.parse(DateFormat.java:579)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at com.oceanlife.rover.handler.XTideParser.parseResponse(XTideParser.java:69)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at com.brantapps.oceanlife.task.SynchroniseTidePosition.doInBackground(SynchroniseTidePosition.java:107)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at com.brantapps.oceanlife.task.SynchroniseTidePosition.doInBackground(SynchroniseTidePosition.java:43)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at android.os.AsyncTask$2.call(AsyncTask.java:295)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at java.util.concurrent.FutureTask.run(FutureTask.java:237)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: at java.lang.Thread.run(Thread.java:818)
偏移量“ 21”是10:59中“ 9”之后的空格。谁能解释这个失败?
更新资料
切换到joda-time,它会显示更多信息的错误消息。这里是;
Invalid format ... is malformed at "PM"
…所以,这是关于要解析的字符串的AM / PM方面-
回到文档
答案1
小编典典在英国语言环境中,“ am”和“ pm”的定义似乎已更改。
在棉花糖中,英国区域设置现在将“ am”表示为“ am”,将“ pm”表示为“ pm”
String record = "2015-10-23 Fri 10:59 p.m. BST 3.60 meters"SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd E hh:mm aa", Locale.UK);// note the length is 25 now, not 23... Date eventDate = dateFormat.parse(StringUtils.substring(record, 0, 25).trim());
我无法解释为什么,但是美国语言环境与am / pm合作,英国与am / pm合作
编辑
似乎在2015年3月的en_gb
语言环境更新中,该语言环境已替换其am /
pm定义。源差异
DateFormat 类和 SimpleDateFormat 类
1.DateFormat 类
花式显示时间和日期。
而且在本机 win10+eclipse 的环境下默认显示当前地区时间。
具体为什么暂时不用管,先记下这个怎么用哈哈哈!贼棒!
import java.text.DateFormat;
import java.util.Date;
public class XJBTEST {
public static void main(String[] args) {
// TODO Auto-generated method stub
DateFormat df1=null;
DateFormat df2=null;
df1 =DateFormat.getDateInstance();
df2 =DateFormat.getDateTimeInstance();
System.out.println("Date"+df1.format(new Date()));
System.out.println("DateTime"+df2.format(new Date()));
}
}
1.SimpleDateFormat 类
花式完成日期的显示格式化。
import java.text.SimpleDateFormat;
import java.util.Date;
public class XJBTEST {
public static void main(String[] args) {
// TODO Auto-generated method stub
String Dataexample="2017-6-12 16:31:13";// 随便打个时间做模板
String Dataorigin="yyyy-MM-dd HH:mm:ss";// 格式
String Datanow="yyyy 年 MM 月 dd 日 HH 时 mm 分 ss 秒";// 目标格式
SimpleDateFormat sdf1=new SimpleDateFormat (Dataorigin);// 实例化模板
SimpleDateFormat sdf2=new SimpleDateFormat (Datanow);// 同上
Date d=null;
try
{
d=sdf1.parse(Dataexample);
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println (sdf2.format (d));// 打印日期为新格式
}
}
一开始老出现问题,结果发现是因为 格式 那一行的字母是不可以 XJB 用的,必须严格按照人家设置好的格式来弄。
这个是粘贴别人的,英文首字母,很好记。
DateTimeFormatter与SimpleDateFormat
日期格式化类:DateTimeFormatter与SimpleDateFormat
一、SimpleDateFormat类
- SimpleDateFormat是用于以对语言环境敏感的方式格式化和解析日期的具体类。
- SimpleDateFormat类的构造方法
NO | 构造器 | 描述 |
---|---|---|
1 | SimpleDateFormat() | SimpleDateFormat使用默认FORMAT语言环境的默认模式和日期格式符号 构造一个。 |
2 | SimpleDateFormat(Stringpattern) | SimpleDateFormat使用给定的模式和默认FORMAT语言环境的默认日期格式符号 构造一个。 |
3 | SimpleDateFormat(Stringpattern,DateFormatSymbolsformatSymbols) | SimpleDateFormat使用给定的模式和日期格式符号构造一个。 |
4 | SimpleDateFormat(Stringpattern,Localelocale) | SimpleDateFormat使用给定语言环境和给定语言环境的默认日期格式符号构造一个。 |
SimpleDateFormat为什么不是线程安全的?
- SimpleDateFormat类的方法没有使用synchronized来给共享变量加锁。
- SimpleDateFormat继承于DateFormat,下面我们看看我们用来格式化的format()方法的部分源码
- DateFormat.java
public final String format(Date date)
{
return format(date, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString();
}
public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition);
- SimpleDateFormat.java
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition pos)
{
// 如此轻易地使用内部变量,肯定不能线程安全
// 线程都对pos进行写操作,必然会影响其他线程的读操作
pos.beginIndex = pos.endIndex = 0;
return format(date, toAppendTo, pos.getFieldDelegate());
}
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
// 这里已经彻底毁坏线程的安全性
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
for (int i = 0; i < compiledPattern.length; ) {
int tag = compiledPattern[i] >>> 8;
int count = compiledPattern[i++] & 0xff;
if (count == 255) {
count = compiledPattern[i++] << 16;
count |= compiledPattern[i++];
}
switch (tag) {
case TAG_QUOTE_ASCII_CHAR:
toAppendTo.append((char)count);
break;
case TAG_QUOTE_CHARS:
toAppendTo.append(compiledPattern, i, count);
i += count;
break;
default:
subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
break;
}
}
return toAppendTo;
}
看源码不用全部看,只需要看重点,不然你会很难受,很耗费时间。SimpleDateFormat类中的format方法的一段代码calendar.setTime(date);
,从这我们可以看出来,如果我们把SimpleDateFormat定义成static成员变量,那么多个thread之间会共享这个SimpleDateFormat对象, 所以Calendar对象也会被共享。那么当有线程A,B操作该方法时,A线程已经给Calendar对象setTime了,但是这时A线程让出了cpu被B线程抢占了,这时B线程在给Calendar对象setTime一个值,然后A线程获得cpu处理,这时A线程以为使用的是它给setTime的值,其实这里的值已经被B线程更改了。这里就会出现线程不安全,因为这里的处理对象都被两个或者更多的线程公用,就会出现线程不安全,所以我们在开发时,尽量使用内部变量,不共享的变量。 3. 实例
package www.com.lining.dateformate;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class DateTimeFormateTest1 {
private static SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
private static String date[] = { "01-Jan-1999", "09-Jan-2000", "08-Jan-2001", "07-Jan-2002", "06-Jan-2003",
"05-Jan-2004", "04-Jan-2005", "03-Jan-2006", "02-Jan-2007" };
public static void main(String[] args) {
for (int i = 0; i < date.length; i++) {
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
String str1 = date[temp];
String str2 = sdf.format(sdf.parse(str1));
System.out.println(Thread.currentThread().getName() + ", " + str1 + "," + str2);
if (!str1.equals(str2)) {
throw new RuntimeException(
Thread.currentThread().getName() + ", Expected " + str1 + " but got " + str2);
}
}
} catch (Exception e) {
throw new RuntimeException("parse failed", e);
}
}
}).start();
}
}
}
- 输出
- 一定要注意cpu的使用权都是需要去抢占的,所以就会出现多线程情况下,出现线程安全问题。
SimpleDateFormat线程不安全的解决方法
- 将SimpleDateFormat定义成局部变量,每次使用时在new 对象。但是每调用一次方法就会创建一个SimpleDateFormat对象,方法结束又要作为垃圾回收,很浪费资源。
- 加一把线程同步锁:synchronized(lock)
public class SyncDateFormatTest {
private static SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
private static String date[] = { "01-Jan-1999", "01-Jan-2000", "01-Jan-2001" };
public static void main(String[] args) {
for (int i = 0; i < date.length; i++) {
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
synchronized (sdf) {
String str1 = date[temp];
Date date = sdf.parse(str1);
String str2 = sdf.format(date);
System.out.println(Thread.currentThread().getName() + ", " + str1 + "," + str2);
if(!str1.equals(str2)){
throw new RuntimeException(Thread.currentThread().getName()
+ ", Expected " + str1 + " but got " + str2);
}
}
}
} catch (Exception e) {
throw new RuntimeException("parse failed", e);
}
}
}).start();
}
}
}
缺点是:每次都要等该锁释放其他的线程才能使用,性能差。 3. 使用ThreadLocal类
- 直接继承与Object类,该类提供了线程局部变量,这些变量不同于他们的普通对应物,因为访问某个变量的每个线程都有自己的局部变量,它独立于变量的初始化副本。
- 每个线程都将拥有自己的SimpleDateFormat对象副本。
public class DateUtil {
private static ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
public static Date parse(String str) throws Exception {
SimpleDateFormat sdf = local.get();
if (sdf == null) {
sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
local.set(sdf);
}
return sdf.parse(str);
}
public static String format(Date date) throws Exception {
SimpleDateFormat sdf = local.get();
if (sdf == null) {
sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
local.set(sdf);
}
return sdf.format(date);
}
}
public class ThreadLocalDateFormatTest {
private static String date[] = { "01-Jan-1999", "01-Jan-2000", "01-Jan-2001" };
public static void main(String[] args) {
for (int i = 0; i < date.length; i++) {
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
String str1 = date[temp];
Date date = DateUtil.parse(str1);
String str2 = DateUtil.format(date);
System.out.println(str1 + "," + str2);
if(!str1.equals(str2)){
throw new RuntimeException(Thread.currentThread().getName()
+ ", Expected " + str1 + " but got " + str2);
}
}
} catch (Exception e) {
throw new RuntimeException("parse failed", e);
}
}
}).start();
}
}
}
这样每个线程都有自己的副本对象SimpleDateFormat,所以每次不同的线程调用的都是自己的副本对象,不会改变其他线程的对象的。
二、DateTimeFormatter类
- jdk1.8中新增了 LocalDate 与 LocalDateTime等类来解决日期处理方法,同时引入了一个新的类DateTimeFormatter来解决日期格式化问题。
- LocalDateTime,DateTimeFormatter两个类都没有线程问题,只要你自己不把它们创建为共享变量就没有线程问题。
- 可以使用Instant代替 Date,LocalDateTime代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate date = LocalDate.parse("2017 06 17", formatter);
System.out.println(formatter.format(date));
- DateTimeFormatter.ofPattern(pattern)的实现
public static DateTimeFormatter ofPattern(String pattern) {
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
}
public final class DateTimeFormatterBuilder extends Object
- TimeFormatterBuilder():用于创建日期时间格式化程序的生成器。
- TimeFormatterBuilder().appendPattern(pattern):将指定模式定义的元素追加到构建器,返回TimeFormatterBuilder对象。
- toFormatter():通过DateTimeFormatter使用默认语言环境创建来完成此构建器,获取DateTimeFormatter对象。
- 模式基于字母和符号的简单序列。模式用于使用ofPattern(String)和ofPattern(String, Locale)方法创建格式化程序 。例如, "d MMM uuuu"将2011-12-03的格式设置为“ 2011年12月3日”。从模式创建的格式化程序可以根据需要多次使用,它是不可变的并且是线程安全的。 例如:
LocalDate日期= LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(“ yyyy MM dd”);
字符串文本= date.format(formatter);
LocalDate parsedDate = LocalDate.parse(text,formatter);
- 其中的LocalDate和LocalDateTime都可以去查看jdk1.8往上的版本api去学习。
DateTimeFormatter和SimpleDateFormat有什么区别?
DateTimeFormatter和SimpleDateFormat都是用于日期时间格式化和解析的类,但它们有以下几个区别:
1.线程安全性:
- DateTimeFormatter 是线程安全的,可以在多线程环境下共享和重用。
- SimpleDateFormat 不是线程安全的,不建议在多线程环境中共享和重用,除非使用适当的同步措施。
2.API 设计:
- DateTimeFormatter 是 Java 8 中引入的,并遵循了新的日期时间 API 的设计原则,提供了一致且易于使用的方法,支持更多的日期时间模式符号和灵活的格式化选项。
- SimpleDateFormat 是早期的 Java 日期时间 API(java.util.Date) 中的类,使用较老的设计风格,并且其 API 比较有限。
3.底层实现:
- DateTimeFormatter 使用基于解析器和格式化器的模型,底层使用 java.time.format.DateTimeFormatterBuilder 类来构建格式化模式。
- SimpleDateFormat 使用基于模式字符串的方式进行格式化和解析,底层使用 java.text.SimpleDateFormat 类。
以下是使用DateTimeFormatter和SimpleDateFormat的代码示例:
使用DateTimeFormatter示例代码:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTimeFormatterExample {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 格式化日期时间
LocalDateTime now = LocalDateTime.now();
String formattedDateTime = formatter.format(now);
System.out.println("格式化后的日期时间:" + formattedDateTime);
// 解析日期时间
String dateTimeString = "2023-07-03 12:30:45";
LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println("解析后的日期时间:" + parsedDateTime);
}
}
打印结果:
格式化后的日期时间:2023-07-03 15:34:58
解析后的日期时间:2023-07-03T12:30:45
使用SimpleDateFormat示例代码:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatExample {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化日期时间
Date now = new Date();
String formattedDateTime = sdf.format(now);
System.out.println("格式化后的日期时间:" + formattedDateTime);
// 解析日期时间
String dateTimeString = "2023-07-03 12:30:45";
try {
Date parsedDateTime = sdf.parse(dateTimeString);
System.out.println("解析后的日期时间:" + parsedDateTime);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
打印结果:
格式化后的日期时间:2023-07-03 15:38:33
解析后的日期时间:Mon Jul 03 12:30:45 CST 2023
在这个示例中,我们分别使用了DateTimeFormatter和SimpleDateFormat来格式化和解析日期时间。它们的用法非常相似,但是需要注意的是,DateTimeFormatter是线程安全的,可以在多线程环境下共享和重用;而SimpleDateFormat不是线程安全的,不建议在多线程环境中共享和重用。
今天的关于ww SimpleDateFormat的奇怪行为和奇怪的英文weird的分享已经结束,谢谢您的关注,如果想了解更多关于Android棉花糖中的SimpleDateFormat行为更改、DateFormat 类和 SimpleDateFormat 类、DateTimeFormatter与SimpleDateFormat、DateTimeFormatter和SimpleDateFormat有什么区别?的相关知识,请在本站进行查询。
本文标签: