V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tangpj
V2EX  ›  Android

Android( Java )日期和时间处理完全解析

  •  
  •   tangpj · 2017-05-04 09:35:37 +08:00 · 5003 次点击
    这是一个创建于 2541 天前的主题,其中的信息可能已经有所发展或是发生改变。
    11 条回复    2017-05-05 09:32:57 +08:00
    TakWolf
        1
    TakWolf  
       2017-05-04 10:32:36 +08:00   ❤️ 2
    重要的几个点,你都给忽略了。。。

    1. 时间的最佳实践是统一使用标准时间格式,即 ISO 8601 标准

    2.为啥在 Android 中使用 `net.danlew:android.joda` 而不直接使用 `joda:joda` ?

    ```
    public class AppController extends Application {

    @Override
    public void onCreate() {
    super.onCreate();
    JodaTimeAndroid.init(this); // 这里是不是要解释一下?
    }

    }
    ```

    3. 结合 Gson 就要结核彻底,都用了 Joda 了,就不要在用任何 Date 相关的了,TyepAdapter 你还给忽略了

    ```
    public final class EntityUtils {

    private EntityUtils() {}

    public static final Gson gson = new GsonBuilder()
    .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter())
    .create();

    private static class DateTimeTypeAdapter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime> {

    @Override
    public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(src.toString()); // 这里自己去匹配格式,建议都用标准 ISO 8601 格式
    }

    @Override
    public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    return new DateTime(json.getAsString());
    }

    }

    }
    ```

    ```
    public class Weibo {

    public DateTime date;

    }
    ```

    ```
    Weibo weobo = gson.fromJson(json,Weibo.class);
    ```
    zhihaofans
        2
    zhihaofans  
       2017-05-04 10:35:13 +08:00 via iPhone
    还以为又是腾讯云的
    ihuotui
        3
    ihuotui  
       2017-05-04 10:56:39 +08:00 via iPhone
    想装逼,结果被打脸
    WispZhan
        4
    WispZhan  
       2017-05-04 11:15:32 +08:00
    基于某种原因,平时就是不喜欢看别人的 Blog 和文章。
    要问为什么?因为基本上所有 Blog 都有这样或者那样的问题,包括我自己的。

    每个人的 Blog 的侧重点都不一样,一般都是写给自己看的,而不是写给别人。
    包括国内的一些书也是一样。写给别人看的东西要严谨,写给自己的东西可以随意。
    domty
        5
    domty  
       2017-05-04 11:26:06 +08:00
    @WispZhan #4
    +1
    blog 这东西我都是当个人 wiki 用的
    tangpj
        6
    tangpj  
    OP
       2017-05-04 11:58:09 +08:00
    @TakWolf
    这里我回复下你的问题
    1、我在关于 DateTime 的介绍中有有一句话:其中 String 的格式需要是 ISO8601 格式,详见:ISODateTimeFormat.dateTimeParser()。你可以点击下这个链接,这个链接就是您说的 IOSO8601 标准的官方网站。而我在文章的最末尾也有一个详细介绍了 IOSO8601 标准的一个表格,你可以详细看看。
    2、为什么使用 net.danlew:android.joda 呢?因为这个是为 Android 设计的一个库,原因是 Android 上的 JAR 设置有个特殊的问题:由于使用了 ClassLoader.getResourceAsStream(),大大增加了它在应用程序上的内存占用。这个库通过从资源而不是从 JAR 家在来避免在 Android 上内存占用的问题(至于为什么要减少内存占用,我相信您是知道的)。同样,在 Android 上用 Rx-Android 的原因不单单是因为要增加支持切换到 UI Thread 的方式哦。也有减少内存占用的原因。解析清楚这点对读者确实是很有必要的。
    3、这篇文章主要是要介绍时间处理的,不是介绍 GSON 也不是介绍 Joda-Time,而介绍时间处理的话就逃不过 Date 这个类。如果想更加简单的话,的确可以通过使用 Gson 的 TypeAdapter 来实现,我在文章中也有提及到了。我之前一直有考虑是不是把您所说的内容加上去的,但是考虑到如果深入探讨的话,就涉及到 Gson 的内容了,我认为没必要。而您的评论恰好是一个比较好的补充。
    最好,感谢您的提醒与指点
    tangpj
        7
    tangpj  
    OP
       2017-05-04 11:59:00 +08:00
    打错了,是最后
    TakWolf
        8
    TakWolf  
       2017-05-04 14:05:09 +08:00
    关于 `为啥在 Android 中使用 net.danlew:android.joda 而不直接使用 joda-time:joda-time 的问题:

    如果你在 Android 使用 android.joda,你必须要在 Application.onCreate()中初始化 JodaAndroid,像这样:

    public class AppController extends Application {

    @Override
    public void onCreate() {
    super.onCreate();
    JodaTimeAndroid.init(this);
    }

    }

    不初始化,不会报错,但是这样就没有任何优势。

    这个就写在 joda-android 的 Readme 中,


    !!!!!但是全文没有任何地方说明这个问题!!!!!


    为什么这里要初始化?

    1. Joda-Time 需要时区的配置(使用 Provider 接口实现),而时区标准是在不断变更和扩充的,经常性更新。
    原版 joda 把它设计为资源数据库,放到 classpath 中加载,joda-android 将其改为 android-resources,对 andorid 更友好。
    joda-android 引用的 joda 为 :joda-time-xxx-no-tzdb,这里不包含时区资源配置。
    初始化这句,就是替换默认的 Provider:

    ```
    DateTimeZone.setProvider(new ResourceZoneInfoProvider(context));
    ```

    这里你不初始化,会走一个默认的。提供的外置时区资源根本不会加载。

    2. Android 手机是可以调时间修改时区的,如果你动态改了时区,joda 的默认时区就不同了,因此需要注册一个 BroadcastReceiver 监听时区变化,来动态修改默认时区。

    ================================================================

    Android Studio 2.4 已经开始支持 Java 8 了,但是却没有 java.time 包,这个不是 BUG!!

    虽然开发需要安装 JDK,但是 java-se 环境跟 Android 环境,使用的核心库跟标准库并不是一个。
    你可以理解为,他们只是使用了相同的接口签名,Android 用的并不是 Java 的核心库。(这就是为啥甲骨文跟谷歌撕逼了好几年) Andorid 的核心库实现在这里:

    %ANDROID_HOME%\sources\android-25

    因此,没有 java.time 包,不是 BUG,单纯是因为这部分包谷歌没有移植!!如果你仔细看,很多核心库的实现都是不一样的!

    ================================================================

    最后,

    文章的标题叫做《 Android ( Java )日期和时间处理完全解析——使用 Gson 和 Joda-Time 优雅地处理日常开发中关于时间处理的问题》

    读完后,没看到完全解析,也没看到优雅,同时提到的 gson 和 joda 也没结合
    tangpj
        9
    tangpj  
    OP
       2017-05-04 15:43:36 +08:00
    @TakWolf
    关于 joda-time 与 joda-android 的问题的确像您所说的一样,我没有写清楚。像您所说的 joda-android 的 readme 文件上已经有了,可能因为我的惯性思维所以没有说明为何这样写,因为我觉得感兴趣的朋友应该会上去 github 上看的。

    ========================================================================

    时区改变的确是一个问题,但是我写 blog 的时候主要考虑是如何让别人能够看懂,所以就没有深入细节了。

    ========================================================================

    blog 上面的代码不是完整的代码,为了方便理解,我只留下了关键的部分。迟点我会把完整的代码上传上去,至于是否优雅,是否完全,是否和 gson 有所结合到时候再下结论吧。

    ========================================================================

    至于第四点,我已经说过了,我不知道为什么 AS 2.4 不能使用 java.time 包。我在 Android O 的官方 API 文档上是看到关于 java.time 包的说明的,API 网址是: https://developer.android.com/reference/java/time/package-summary.html 。所以我就推测是 AS 2.4 还没提供支持的原因。
    至于您说的 Android 用的并不是 Java 的核心库这个问题,我并没有深入了解过。我迟点会加深理解的。

    这里我要说明我写博客的原因。一个是,我怕做过的东西不记录下来的话,很容易会遗忘。第二个就是我希望有人能指出我理解不到位的地方,所以您能指出我的不足之处我是十分感谢的。
    29995270
        10
    29995270  
       2017-05-05 00:16:11 +08:00 via Android   ❤️ 1
    楼主态度这么好,不知道为啥回复不是阴阳怪气就是跟吃了枪药似的,写得不错,支持。
    tangpj
        11
    tangpj  
    OP
       2017-05-05 09:32:57 +08:00
    @29995270 十分感谢哦😊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5791 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 02:59 · PVG 10:59 · LAX 19:59 · JFK 22:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.