- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在开发一个应用程序,其中一部分是向服务器发出http请求,然后从头部解析服务器日期和时间。按以下方式进行:
//The format used here typically looks like this: "Tue, 08 Jul 2124 13:34:21 GMT-8"
final SimpleDateFormat serverDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
String string = response.headers.get("Date"); // this is where we get the Date and Time value
Date date = serverDateFormat.parse(string); // this is where we parse that string into the Date format
long result = date.getTime(); // this is where we translate it into millisec format
Log.e(TAG,"Date in milliseconds: "+result);
SimpleDateFormat
忽略解析字符串中的时区。这是保持原始服务器时间所必需的。如果我们分析时区,
Date
变量将自动将时间调整到设备的时区(因此,如果他得到格林尼治标准时间21点,并且设备的时区是格林尼治标准时间2,那么输出将是19点)。
最佳答案
正如@Matt's answer中所解释的,忽略偏移量(gmt-8)并不是一件好事,因为SimpleDateFormat
将使用系统的默认时区-并且此时区在每个设备/环境中可能不同,并且您无法控制它。即使默认时区是正确的,它也可以更改,即使是在运行时,所以您不能假设它总是您所需要的。
示例:我的默认时区是America/Sao_Paulo
,当前偏移量是-03:00
(或GMT-3
,或比UTC晚3小时)。如果我使用您的代码,它将假定它在圣保罗是13:34(在UTC中是16:34-毫秒值是4876130061000
,这是错误的,因为它不等于原始输入(在GMT-8中是13:34)。
只有当我将默认时区更改为GMT-8
时,代码才会给出正确的值。要不依赖于此,可以设置格式化程序的时区。SimpleDateFormat
has some patterns to parse timezone/offset,但它们都不能与GMT-8
一起工作(它似乎只接受GMT-08:00
),因此一种解决方案是从输入中删除它,并使用它为格式化程序设置正确的时区:
String input = "Tue, 08 Jul 2124 13:34:21 GMT-8";
String[] v = input.split(" GMT"); // split the string, before and after "GMT"
SimpleDateFormat serverDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH);
// set the formatter timezone to the offset (in this case, to "GMT-8")
serverDateFormat.setTimeZone(TimeZone.getTimeZone("GMT" + v[1]));
// parse the date/time part
Date date = serverDateFormat.parse(v[0]);
4876148061000
,相当于
2124-07-08T21:34:21Z
(21:34 UTC=13:34,GMT-8)。
System.out.println(date);
Date::toString
方法,该方法获取millis值并转换为系统的默认时区,给人一种错误的印象,即日期对象具有时区-
but that's wrong:日期只包含自
1970-01-01T00:00Z
以来的毫秒数。
toString
通常在调试器中看到日期时也会调用
SimpleDateFormat
并在此格式化程序中设置所需的时区。使用
Date::toString
总是误导您关于值的认识。
SimpleDateFormat
并将
GMT-8
设置为它,如下所示:
// display the date in a specific format
SimpleDateFormat outputFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
// use the same offset used by the server (GMT-8)
outputFormat.setTimeZone(TimeZone.getTimeZone("GMT-8"));
System.out.println(outputFormat.format(date)); // 08/07/2124 13:34:21
Locale.ENGLISH
来解析输入。这是必需的,因为一周中的月和日都是英文的。如果我没有指定
java.util.Locale
,格式化程序将使用系统的默认值,并且不能保证它总是英文的。这也可以在运行时更改,因此最好使用显式的,而不是依赖默认值。
Date
、
Calendar
和
SimpleDateFormat
)有
lots of problems和
design issues,它们正在被新的api替换。
org.threeten.bp.OffsetDateTime
将其解析为
org.threeten.bp.format.DateTimeFormatter
。
SimpleDateFormat
没有给出这个错误,因为大家都知道它过于宽大,忽略了很多错误,并试图以不那么聪明的方式“修复”(这可能有点基于意见,但许多人认为这是一件坏事,这就是为什么新的api对此更加严格的原因)。
String input = "Sat, 08 Jul 2124 13:34:21 GMT-8";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("EE, dd MMM yyyy HH:mm:ss O", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse(input, parser);
odt
相当于
2124-07-08T13:34:21-08:00
。
// the same value as date.getTime()
long millis = odt.toInstant().toEpochMilli();
java.util.Date
,可以使用
org.threeten.bp.DateTimeUtils
类:
// convert to java.util.Date
Date date = DateTimeUtils.toDate(odt.toInstant());
DateTimeFormatter
。由于
OffsetDateTime
保持正确的值,因此无需在格式化程序中设置时区:
// display date in a specific format
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
System.out.println(odt.format(outputFormat)); // 08/07/2124 13:34:21
org.threeten.bp.ZoneId
和
org.threeten.bp.ZoneOffset
:
// convert to UTC
System.out.println(outputFormat.format(odt.withOffsetSameInstant(ZoneOffset.UTC)));
// convert to offset +05:00
System.out.println(outputFormat.format(odt.withOffsetSameInstant(ZoneOffset.ofHours(5))));
// convert to Europe/Berlin timezone
System.out.println(outputFormat.format(odt.atZoneSameInstant(ZoneId.of("Europe/Berlin"))));
Europe/Berlin
。
Continent/City
格式,如
America/Sao_Paulo
或
Europe/Berlin
)。
CST
或
PST
),因为它们是
IANA timezones names。
ZoneId.getAvailableZoneIds()
获得所有可用时区的列表(并相应地选择)。
关于android - Android设备错误地解析了服务器中的日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45643745/
我最近在/ drawable中添加了一些.gifs,以便可以将它们与按钮一起使用。这个工作正常(没有错误)。现在,当我重建/运行我的应用程序时,出现以下错误: Error: Gradle: Execu
Android 中有返回内部存储数据路径的方法吗? 我有 2 部 Android 智能手机(Samsung s2 和 s7 edge),我在其中安装了一个应用程序。我想使用位于这条路径中的 sqlit
这个问题在这里已经有了答案: What's the difference between "?android:" and "@android:" in an android layout xml f
我只想知道 android 开发手机、android 普通手机和 android root 手机之间的实际区别。 我们不能从实体店或除 android marketplace 以外的其他地方购买开发手
自Gradle更新以来,我正在努力使这个项目达到标准。这是一个团队项目,它使用的是android-apt插件。我已经进行了必要的语法更改(编译->实现和apt->注释处理器),但是编译器仍在告诉我存在
我是android和kotlin的新手,所以请原谅要解决的一个非常简单的问题! 我已经使用导航体系结构组件创建了一个基本应用程序,使用了底部的导航栏和三个导航选项。每个导航选项都指向一个专用片段,该片
我目前正在使用 Facebook official SDK for Android . 我现在正在使用高级示例应用程序,但我不知道如何让它获取应用程序墙/流/状态而不是登录的用户。 这可能吗?在那种情
我在下载文件时遇到问题, 我可以在模拟器中下载文件,但无法在手机上使用。我已经定义了上网和写入 SD 卡的权限。 我在服务器上有一个 doc 文件,如果用户单击下载。它下载文件。这在模拟器中工作正常但
这个问题在这里已经有了答案: What is the difference between gravity and layout_gravity in Android? (22 个答案) 关闭 9
任何人都可以告诉我什么是 android 缓存和应用程序缓存,因为当我们谈论缓存清理应用程序时,它的作用是,缓存清理概念是清理应用程序缓存还是像内存管理一样主存储、RAM、缓存是不同的并且据我所知,缓
假设应用程序 Foo 和 Eggs 在同一台 Android 设备上。任一应用程序都可以获取设备上所有应用程序的列表。一个应用程序是否有可能知道另一个应用程序是否已经运行以及运行了多长时间? 最佳答案
我有点困惑,我只看到了从 android 到 pc 或者从 android 到 pc 的例子。我需要制作一个从两部手机 (android) 连接的 android 应用程序进行视频聊天。我在想,我知道
用于使用 Android 以编程方式锁定屏幕。我从 Stackoverflow 之前关于此的问题中得到了一些好主意,并且我做得很好,但是当我运行该代码时,没有异常和错误。而且,屏幕没有锁定。请在这段代
文档说: android:layout_alignParentStart If true, makes the start edge of this view match the start edge
我不知道这两个属性和高度之间的区别。 以一个TextView为例,如果我将它的layout_width设置为wrap_content,并将它的width设置为50 dip,会发生什么情况? 最佳答案
这两个属性有什么关系?如果我有 android:noHistory="true",那么有 android:finishOnTaskLaunch="true" 有什么意义吗? 最佳答案 假设您的应用中有
我是新手,正在尝试理解以下 XML 代码: 查看 developer.android.com 上的文档,它说“starStyle”是 R.attr 中的常量, public static final
在下面的代码中,为什么当我设置时单选按钮的外观会发生变化 android:layout_width="fill_parent" 和 android:width="fill_parent" 我说的是
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
假设我有一个函数 fun myFunction(name:String, email:String){},当我调用这个函数时 myFunction('Ali', 'ali@test.com ') 如何
我是一名优秀的程序员,十分优秀!