我发现了一种奇怪的行为,这让我感到很好奇,而且还没有令人满意的解释.
为简单起见,我已将我注意到的症状减少到以下代码:
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
public class CalendarTest {
public static void main(String[] args) {
System.out.println(new SimpleDateFormat().getCalendar());
System.out.println(new GregorianCalendar());
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,我得到的内容与以下输出非常相似:
java.util.GregorianCalendar[time=-1274641455755,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=1929,MONTH=7,WEEK_OF_YEAR=32,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=222,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=55,SECOND=44,MILLISECOND=245,ZONE_OFFSET=-28800000,DST_OFFSET=0] java.util.GregorianCalendar[time=1249962944248,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2009,MONTH=7,WEEK_OF_YEAR=33,WEEK_OF_MONTH=3,DAY_OF_MONTH=10,DAY_OF_YEAR=222,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=55,SECOND=44,MILLISECOND=248,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]
(如果我提供类似于"yyyy-MM-dd"SimpleDateFormat 的有效格式字符串,也会发生同样的事情.)
原谅可怕的非包裹线,但这是比较两者的最简单方法.如果您滚动到大约2/3的路径,您将看到日历的YEAR值分别为1929和2009.(还有一些其他差异,例如一周中的一周,一周中的某一天和DST偏移.)两者显然都是GregorianCalendar的实例,但它们之所以不同是令人费解的.
据我所知,格式化器在格式化传递给它的Date对象时生成准确.显然,正确的功能比正确的参考年份更重要,但差异仍然令人不安.我不认为我必须在一个全新的日期格式化程序上设置日历才能获得当前年份......
我在使用Java 5(OS X 10.4,PowerPC)和Java 6(OS X 10.6,Intel)的Mac上进行了测试,结果相同.由于这是一个Java库API,我认为它在所有平台上的行为都相同.对这里正在发生的事情的任何见解?
(注意:这个SO问题有些相关,但不一样.)
编辑:
以下答案都有助于解释这种行为.事实证明,SimpleDateFormat的Javadocs 实际上在某种程度上证明了这一点:
"对于使用缩写年份模式("y"或"yy")进行解析,SimpleDateFormat必须解释相对于某个世纪的缩写年份.它通过将日期调整为在SimpleDateFormat实例之前的20年之前和20年之后来实现这一点.被建造."
因此,他们不会对解析日期的年份感到满意,而是默认将内部日历设置为80年.这部分本身没有记录,但是当你知道它时,这些部分都是合在一起的.
我一直在调试一些现有的代码,我的系统上的单元测试失败了,但同事的系统却没有.根本原因是SimpleDateFormat在解析应该可解析的日期时抛出ParseExceptions.我创建了一个单元测试,演示了我的系统失败的代码:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import junit.framework.TestCase;
public class FormatsTest extends TestCase {
public void testParse() throws ParseException {
DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
formatter.setTimeZone(TimeZone.getDefault());
formatter.setLenient(false);
formatter.parse(formatter.format(new Date()));
}
}
Run Code Online (Sandbox Code Playgroud)
此测试在我的系统上抛出ParseException,但在其他系统上成功运行.
java.text.ParseException: Unparseable date: "20100603100243.118 -0600"
at java.text.DateFormat.parse(DateFormat.java:352)
at FormatsTest.testParse(FormatsTest.java:16)
Run Code Online (Sandbox Code Playgroud)
我发现我可以setLenient(true),测试会成功.该setLenient(false)是什么样的生产代码,本次测试模拟使用,所以我不想去改变它.
使用Java Date实用程序时的真正含义是什么并且已被弃用.这是否意味着不鼓励使用,还是暗示它被禁止?
我猜测使用弃用方法是不好的做法,但我不确定并想知道.
例如,我正在尝试使用如下代码
String date = request.getParameter("date");
model.setDate(new Date(date));
Run Code Online (Sandbox Code Playgroud)
当然......这是一个高级示例,但在这种情况下,我的模型使用Date类型,我需要将请求中的日期作为String拉出并使用它创建日期.
我的工作方式很好,但它使用的是不推荐使用的方法.
编辑 - 我已经回去使用了
SimpleDateFormat formatter = new SimpleDateFormat();
model.setDate(formatter.parse(request.getParameter("date");
日期的格式为MM/DD/YYY,如07/23/2010,但我收到了ParseException
这可能是什么?
我需要构建一个类似的日期格式dd/MM/yyyy.它几乎就像DateFormat.SHORT,但包含4年的数字.
我尝试用它来实现它
new SimpleDateFormat("dd//MM/yyyy", locale).format(date);
Run Code Online (Sandbox Code Playgroud)
但是对于美国语言环境,格式错误.
是否有一种通用的方法来格式化基于区域设置更改模式的日期?
谢谢
Java 7 SimpleDateFormat通过字符X(而不是大写或小写Z)在ISO 8601格式的类中引入了支持.在Java 6中支持这样的格式需要预处理,因此最好的方法是问题.
这种新格式是Z(大写Z)的超集,另外还有两种变体:
因此,正如人们可以从Java 7文档中SimpleDateFormat看到的那样,以下3种格式现在是有效的(而不仅仅是ZJava 6中涵盖的第二种格式),当然,等效:
正如之前关于支持这种"扩展"时区格式的特殊情况的问题所讨论的那样,始终使用':'作为分隔符,将Java 7功能向后移植到Java 6中的最佳方法是将类子SimpleDateformat类化并覆盖其parse()方法,即:
public Date parse(String date, ParsePosition pos)
{
String iso = ... // Replace the X with a Z timezone string, using a regex
if (iso.length() == date.length())
{
return null; // Not an ISO 8601 date
}
Date parsed …Run Code Online (Sandbox Code Playgroud) 我试图解析字符串"2/20/2012 12:00:00 AM"使用SimpleDateFormat,并且它似乎不是来了12点.
Date fromFmt = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss aa")
.parse("2/20/2012 12:00:00 AM");
// Calendar months are 0-indexed
Date fromCal = new Date(new GregorianCalendar(2012, 1, 20, 0, 0, 0)
.getTimeInMillis());
System.out.println(fromFmt);
System.out.println(fromCal);
Run Code Online (Sandbox Code Playgroud)
输出:
Mon Feb 20 12:00:00 PST 2012
Mon Feb 20 00:00:00 PST 2012
Run Code Online (Sandbox Code Playgroud)
我希望他们两个都输出后者.我的格式字符串有问题吗?
(并且请没有人说'使用JodaTime'.)
我收到的String是一周的拼写日,例如星期一.现在我想得到那天使用的常量整数表示java.util.Calendar.
我真的必须自己做if(day.equalsIgnoreCase("Monday")){...}else if(...){...}吗?有一些简洁的方法吗?如果我挖出SimpleDateFormat并与Calendar我混合产生几乎与打字丑陋的if-else-infitity statetment一样多的行.
好吧,我正在使用一个详细信息Date,因为我从我的DataBase和变量"fecha"(日期)中得到一个对象我得到的同一个对象java.sql.Timestamp,所以格式是毫秒,但我不希望出现毫秒.所以我需要将我从数据库接收的日期格式化为没有毫秒数的新日期.
这是Factura的对象:
public class Factura implements java.io.Serializable {
private FacturaId id;
...
private boolean activo;
private Date fecha;
}
Run Code Online (Sandbox Code Playgroud)
在映射到DB的xml中,我有这个变量"fecha"的代码:
<property name="fecha" type="timestamp">
<column length="19" name="fecha" not-null="true"/>
</property>
Run Code Online (Sandbox Code Playgroud)
在列的数据库中fecha DATETIME.
当我Factura从我的数据库中获取一个对象时,我得到了这样的约会,2013-10-10 10:49:29.0但我希望它没有.0(毫秒).
我试过这个(factura是Factura对象):
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date fechaNueva = null;
String fechaStr = factura.getFecha().toString();
int tamaño = fechaStr.length()-2;
fechaStr = fechaStr.substring(0, tamaño); //I get a string without the miliseconds …Run Code Online (Sandbox Code Playgroud) 我SimleDateFormat喜欢这个
SimpleDateFormat format = new SimpleDateFormat("MMM dd,yyyy hh:mm");
String date = format.format(Date.parse(payback.creationDate.date));
Run Code Online (Sandbox Code Playgroud)
我给的日期格式是这样的"Jan,23,2014".
现在,我希望分别获得日,月和年.我该如何实现呢?
这是我约会的日期"15-05-2014 00:00:00"
如何将IST转换为UTC即(至14-05-2014 18:30:00)
我的代码是
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("IST")); //here set timezone
System.out.println(formatter.format(date));
formatter.setTimeZone(TimeZone.getTimeZone("UTC")); //static UTC timezone
System.out.println(formatter.format(date));
String str = formatter.format(date);
Date date1 = formatter.parse(str);
System.out.println(date1.toString());
Run Code Online (Sandbox Code Playgroud)
如果用户从任何区域输入相同的日期,那么将获得UTC时间(例如:从澳大利亚然后15-05-2014 00:00:00到14-05-2014 16:00:00)
请任何建议.
java ×10
simpledateformat ×10
date ×7
calendar ×3
android ×1
dayofweek ×1
deprecated ×1
java-6 ×1
locale ×1
netbeans-7.1 ×1
regex ×1
timestamp ×1
timezone ×1