无法在Android中将ISO 8601日期转换为String

时间:2017-09-04 23:29:12

标签: android simpledateformat date-format datetime-parsing

我有一个Android应用程序,它显示了我从服务器获取信息的故障单的创建日期。

问题是当我尝试使用SimpleDateFormat解析它时,我无法解析我得到的字符串

这是我从服务器获得的:

2017-07-04 23:59:51.486559-05

这是我用来解析它的格式:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSX", Locale.ENGLISH);

我采用这种方法的例外是:

java.lang.IllegalArgumentException: Unknown pattern character 'X'
 at java.text.SimpleDateFormat.validatePatternCharacter(SimpleDateFormat.java:323)
 at java.text.SimpleDateFormat.validatePattern(SimpleDateFormat.java:312)
 at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:365)
 at com.unipagos.app.wallet.payment.receipts.datamodels.PaymentReceipt.dateFromString(PaymentReceipt.java:320)

我已经在那里待了好几个小时了,我也试过了

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.ENGLISH);

无济于事,获得此例外:

java.text.ParseException: Unparseable date: "2016-05-30 20:41:19.934959+00" (at offset 23)
 at java.text.DateFormat.parse(DateFormat.java:579)
 at com.unipagos.app.wallet.payment.receipts.datamodels.PaymentReceipt.dateFromString(PaymentReceipt.java:326)
 at com.unipagos.app.wallet.payment.receipts.datamodels.PaymentReceipt.loadReceiptJSONObject(PaymentReceipt.java:164)
 at com.unipagos.app.history.HistoryListFragment.populateTransactionList(HistoryListFragment.java:371)
 at com.unipagos.app.history.HistoryListFragment.access$3200(HistoryListFragment.java:83)

我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

SimpleDateFormat无法解析您的日期时间字符串。该字符串有微秒(秒数为6位小数),其中Date仅支持毫秒(3位小数)。

ThreeTenABP

因此,这似乎是您放弃过时的过时课程SimpleDateFormat DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSX", Locale.ENGLISH); OffsetDateTime odt = OffsetDateTime.parse(creationDateFromServer, dtf); System.out.println(odt); 的好机会。一般经验表明,现代Java日期和时间API可以更好地使用。对于Android,您可以在 ThreeTenABP 中找到它,链接如下。当你知道如何时,其余的都很简单:

2017-07-04T23:59:51.486559-05:00

打印

2017-07-04 23:59:51.486559-05

这与您的输入toString()一致。顺便说一下,印刷的字符串是ISO 8601;这就是现代类'Z方法产生的结果。

老式解决方案

如果你坚持坚持过时的类,一个方法就是去除最后三位小数,这样只有三位小时,为时区偏移添加两位数,所以有四位,并使用 creationDateFromServer = creationDateFromServer .replaceFirst("(\\.\\d{3})\\d{3}((?:\\+|-)\\d{2})$", "$1$200"); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.ENGLISH); try { Date d = df.parse(creationDateFromServer); System.out.println(d); } catch (ParseException pe) { System.out.println(pe + " at offset " + pe.getErrorOffset()); } 解析它:

Wed Jul 05 06:59:51 CEST 2017

请注意阅读正则表达式有多难。如果偏移量达到例如+0530一天,这将会中断。输出是:

Date

我的本​​地时区Date 打印,在这种情况下偏移+0200,因此打印时间与前一天的23:59:51.486-0500一致。这意味着 @Override protected void onResume() { super.onResume(); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter != null) { if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } else { scanAndPairDevice(); } } else { // TODO Android Device doesnt Support Bluetooth } } private void scanAndPairDevice() { if (isDevicePaired()) { receiveDataFromDevice(); } else { if(flag!=1) { showAlertDialog(mContext, "SPLTECH Device is not paired!", "Please pair the device to connect", 1); } else { showAlertDialog(mContext, "SPLTECH Device is not registered!", "Please conect with a registered device", 3); } //getDeviceListFromServer(); } } private boolean isDevicePaired() { Set<BluetoothDevice> bluetoothDeviceSet = mBluetoothAdapter.getBondedDevices(); if (bluetoothDeviceSet.size() > 0) { Set<String> set=mSesssion.getDeviceList(); Iterator<BluetoothDevice> iT=bluetoothDeviceSet.iterator(); while(iT.hasNext()){ BluetoothDevice device=iT.next(); for(String device1: set) { if(device.getName().equals("SPLTECH")) { flag=1; } if(device.getAddress().equals(device1)) { mDevice = device; mSesssion.setDeviceMacId(device.getAddress()); return true; } } } } return false; } private void receiveDataFromDevice() { mProgressBar.setVisibility(View.GONE); mHint.setVisibility(View.VISIBLE); Toast.makeText(mContext, "Now,Bluetooth is Ready to Take Value From Device..!", Toast.LENGTH_SHORT).show(); myThreadConnectBTdevice = new ThreadConnectBTdevice(); myThreadConnectBTdevice.start(); } private class ThreadConnectBTdevice extends Thread { private BluetoothSocket bluetoothSocket = null; private ThreadConnectBTdevice() { try { Log.i("hii","hello"); //bluetoothSocket = mDevice.createRfcommSocketToServiceRecord(myUUID); Method m = mDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); bluetoothSocket = (BluetoothSocket) m.invoke(mDevice, 1); } catch (Exception e) { // TODO Auto-generated catch block Log.i("hii","hello"); e.printStackTrace(); } } @Override public void run() { boolean success = false; try { bluetoothSocket.connect(); success = true; } catch (IOException e) { e.printStackTrace(); final String eMessage = e.getMessage(); runOnUiThread(new Runnable() { @Override public void run() { // textStatus.setText("something wrong bluetoothSocket.connect(): \n" + eMessage); } }); try{ bluetoothSocket.close(); } catch (IOException ex) { } } if (success) { //connect successful startThreadConnected(bluetoothSocket); } else { //fail Log.i("hii","in false"); } } public void cancel() { try { bluetoothSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void startThreadConnected(BluetoothSocket socket) { myThreadConnected = new ThreadConnected(socket); myThreadConnected.start(); } /* ThreadConnected: Background Thread to handle Bluetooth data communication after connected */ private class ThreadConnected extends Thread { private final BluetoothSocket connectedBluetoothSocket; private final InputStream connectedInputStream; private final OutputStream connectedOutputStream; public ThreadConnected(BluetoothSocket socket) { connectedBluetoothSocket = socket; InputStream in = null; OutputStream out = null; try { in = socket.getInputStream(); out = socket.getOutputStream(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } connectedInputStream = in; connectedOutputStream = out; } @Override public void run() { byte[] buffer = new byte[1024]; int bytes; while (true) { try { bytes = connectedInputStream.read(buffer); final String strReceived = new String(buffer, 0, bytes); Log.d("abc", strReceived); Message readMsg = mHandler.obtainMessage( DATA_FROM_DEVICE, strReceived); readMsg.sendToTarget(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); final String msgConnectionLost = "Connection lost:\n" + e.getMessage(); runOnUiThread(new Runnable() { @Override public void run() { mHint.setText(msgConnectionLost); } }); break; } } } public void write(byte[] buffer) { try { connectedOutputStream.write(buffer); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void cancel() { try { connectedBluetoothSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 对象内部保持正确的时间点。

链接

How to use ThreeTenABP in Android Project