now()
的以下代码对对象执行两次。一次表示它的创建,另一次表示它何时被写入数据库。
在受控测试中,我设法可靠地重现了日期彼此之间变化很大的错误。某些日期似乎有正确的日期,但是00:00:00
或接近00:00:00
。
其他人似乎相对较弱,从1小时到16周甚至几周不等。我也有未来的时间。 Calendar.getInstance.getTime()
应该等同于System.getCurrentTimeMillis()
,让后者在一段时间内返回未来的时间后会担心一些。
我还没找到任何东西,并会进一步调查这个问题并在此报告我的发现。
private static DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public static String calendarToDb(Calendar cal) {
if (cal == null) {
return null;
}
return simpleDateFormat.format(cal.getTime());
}
public static String now() {
return calendarToDb(Calendar.getInstance());
}
这是android-monitor日志的相关部分。这是一个真实的设备,而不是模拟器。 M代表MessageManager,P代表ContentProvider
08-30 18:07:17.267 M: main starttime = 2016-01-01T00:07:00+0100\
08-30 18:07:17.306 P: AsyncQueryWorker CreateTime = 2016-08-30T18:07:17+0200\
08-30 18:07:18.326 M: main starttime = 2016-01-01T00:00:00+0200\
08-30 18:07:18.371 P: AsyncQueryWorker CreateTime = 2016-08-30T18:07:18+0200\
08-30 18:07:19.898 M: main starttime = 2016-08-30T18:07:19+0200\
08-30 18:07:19.920 P: AsyncQueryWorker CreateTime = 2016-08-30T00:00:00+0100\
我的数据库中有更多数据看起来更奇怪,根本不应该发生。
答案 0 :(得分:3)
问题似乎很可能出现在静态
中Sub SearchFolders()
Dim fso As Object
Dim fld As Object
Dim strSearch As String ' Keyword to search for
Dim strPath As String ' Filepath of folder to search
Dim strFile As String ' current file that the loop is searching through
Dim wOut As Worksheet ' Worksheet to display results
Dim wbk As Workbook ' Workbook to be searched
Dim wks As Worksheet ' Worksheet to be searched
Dim lRow As Integer
Dim rFound As Range
Dim strFirstAddress As String
Application.ScreenUpdating = False
'Change as desired
strPath = "\\ant\dept-eu\LTN1\Techies Information\aa Eng daily log"
strSearch = InputBox("Insert Keyword to search")
Set wOut = Sheet1
lRow = 1
With wOut
Sheet1.Cells.Clear
.Cells(lRow, 1) = "Workbook"
.Cells(lRow, 2) = "Worksheet"
.Cells(lRow, 3) = "Text in Cell"
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(strPath)
strFile = Dir(strPath & "\*.xls*")
Do While strFile <> ""
Set wbk = Workbooks.Open _
(Filename:=strPath & "\" & strFile, _
UpdateLinks:=0, _
ReadOnly:=True, _
AddToMRU:=False)
For Each wks In wbk.Worksheets ' for each worksheet
Set rFound = wks.UsedRange.Find(strSearch) ' setting variable to first result in find function
If Not rFound Is Nothing Then ' if something is found
strFirstAddress = rFound.Address ' set first address to that cell's address
End If
Do
If rFound Is Nothing Then ' if nothing was found
Exit Do ' exit loop
Else ' if something was found then add the details to the table
lRow = lRow + 1
.Cells(lRow, 1) = wbk.Name
.Cells(lRow, 2) = wks.Name
.Cells(lRow, 3) = rFound.Value
End If
Set rFound = wks.Cells.FindNext(After:=rFound) ' sets rfound vaiable to next found value
Loop While strFirstAddress <> rFound.Address ' once the find function gets back to the first address then exit the loop
Next ' next worksheet in file
wbk.Close (False)
strFile = Dir
Loop
.Columns("A:D").EntireColumn.AutoFit
End With
MsgBox "Done"
ExitHandler:
Set wOut = Nothing
Set wks = Nothing
Set wbk = Nothing
Set fld = Nothing
Set fso = Nothing
Application.ScreenUpdating = True
Exit Sub
如下所述: Why is Java's SimpleDateFormat not thread-safe?
存储中间结果,如果多个线程使用相同的实例(由于静态,它们会执行)。时间可以在方法执行期间部分重置,这会扭曲当前处理的结果。
解决方案是每次都返回新实例。
答案 1 :(得分:1)
The Answer by HopefullyHelpful is correct, and should be accepted. You are likely seeing errors due to the lack of thread-safety in the old date-time classes. This is one of many reasons to avoid these troublesome old legacy date-time classes.
Instead you should be using the java.time classes. The java.time classes have thread-safety baked-in.
Your input strings happen to comply with the ISO 8601 standard for date-time formats.
The java.time classes use ISO 8601 formats by default when parsing/generating Strings. So you should not need to specify a formatting pattern but for a bug in the current Java 8 implementation. Currently the lack of a colon in the offset-from-UTC causes parsing to fail by default. Should be fixed in Java 9. While in Java 8 specify a pattern with DateTimeFormatter
and DateTimeFormatterBuilder
.
String input = "2016-08-30T18:07:17+0200";
DateTimeFormatterBuilder fb = new DateTimeFormatterBuilder ().append ( DateTimeFormatter.ISO_LOCAL_DATE_TIME ).appendOffset ( "+HHMM" , "Z" );
DateTimeFormatter f = fb.toFormatter ();
OffsetDateTime
Your input strings indicate an offset-from-UTC but not a full time zone. So we parse as OffsetDateTime
objects.
In Java 9 and later, parse directly:
OffsetDateTime odt = OffsetDateTime.parse ( input );
In Java 8, use the DateTimeFormatter
object built above.
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
Dump to console.
System.out.println ( "input: " + input + " | odt: " + odt );
input: 2016-08-30T18:07:17+0200 | odt: 2016-08-30T18:07:17+02:00