[cocos2d-x] ISO8601拡張表記(UTC)の時刻をローカルのタイムゾーンに変換する

ISO8601拡張表記(UTC)の時刻の文字列を端末に設定されているタイムゾーンに変換する方法。
端末のタイムゾーンを取得する方法が標準であるかなと思ったけど、見つけられなかったのでJNIを使った。

## 想定する場面
WebAPIなどから受け取る時刻の形式が、"2016-02-05T04:29:30Z"となっているが、
画面上に表示する形式は端末に設定されているタイムゾーンに変換した上で
"2016-02-05 13:29:30"となるようにしたい。

## 共通ヘッダ

```cpp:Classes/native/TimeHelper.h
#ifndef ___native_TimeHelper___
#define ___native_TimeHelper___

namespace native {

    class TimeHelper {
    public:
        /**
         * ISO8601拡張表記の文字列をローカル時刻の文字列に変換する
         *
         * 変換例: 端末のタイムゾーンが日本標準時(+09:00)の場合
         * "2016-02-05T04:29:30Z" => "2016-02-05 13:29:30"
         *
         * @param iso8601TimeString ISO8601拡張表記の文字列 "yyyy-MM-dd'T'HH:mm:ss'Z'"
         * @return "yyyy-mm-dd HH:MM:SS"の形式
         */
        static std::string convertToLocalTimeForDisplay(std::string iso8601TimeString);
    };
}

#endif
```

## Android用

```cpp:Classes/native/TimeHelper.cpp
#include "native/TimeHelper.h"
#include "cocos2d.h"
#include "platform/android/jni/JniHelper.h"

USING_NS_CC;
using namespace native;

std::string TimeHelper::convertToLocalTimeForDisplay(std::string iso8601TimeString) {
    cocos2d::JniMethodInfo methodInfo;

    auto className = "org.cocos2dx.cpp.util.TimeHelper";
    auto methodName = "convertToLocalTimeForDisplay";
    if (!cocos2d::JniHelper::getStaticMethodInfo(methodInfo, className, methodName, "(Ljava/lang/String;)Ljava/lang/String;")) {
        log("Failed to find static method of %s#%s", className, methodName);
        return iso8601TimeString;
    }

    jstring jstrTimeString = methodInfo.env->NewStringUTF(iso8601TimeString.c_str());
    jobject objResult = methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, jstrTimeString);
    std::string ret = JniHelper::jstring2string((jstring)objResult);
    log("convert to local time: %s", ret.c_str());

    methodInfo.env->DeleteLocalRef(methodInfo.classID);

    return ret;
}
```

## iOS用

```cpp:Classes/native/TimeHelper.mm
#include "../native/TimeHelper.h"
#include "cocos2d.h"

USING_NS_CC;
using namespace native;

std::string TimeHelper::convertToLocalTimeForDisplay(std::string iso8601TimeString) {
    // ISO8601形式の文字列をNSDateに変換
    // formatterにタイムゾーンを指定しない場合、
    // ローカルのタイムゾーンが適用されたNSDateが取得できるはず
    NSString *utcIso8601String = [NSString stringWithUTF8String:iso8601TimeString.c_str()];
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
    NSDate* date = [formatter dateFromString:utcIso8601String];
    [formatter release];

    // 目的の書式に変換する
    formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString* localDateString = [formatter stringFromDate:date];
    [formatter release];

    return [localDateString UTF8String];
}
```
***

## ネイティブ側(Android)

```java:org/cocos2dx/cpp/util/TimeHelper.java
package org.cocos2dx.cpp.util;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class TimeHelper {

    /**
     * ISO8601拡張表記の文字列をローカル時刻で返す
     *
     * @param iso8601UTCString ISO8601拡張表記の世界標準時刻の文字列
     * @return "yyyy-mm-dd HH:MM:SS"形式のローカル時刻
     */
    public static String convertToLocalTimeForDisplay(String iso8601UTCString) {
        try {
            // ローカルタイムゾーンに変換
            SimpleDateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
            iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date = iso8601Format.parse(iso8601UTCString);

            // 書式を指定して返す
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getDefault());

            return sdf.format(date);
        }catch(Exception e) {
            return null;
        }
    }
}

```

## Android.mk

LOCAL_SRC_FILESにTimeHelper.cppを追加する

```mf:proj.android-studio/app/jni/Android.mk
...
LOCAL_SRC_FILES := hellocpp/main.cpp \
...
                   ../../../Classes/native/TimeHelper.cpp \
...
```

## iOSの注意点
XCodeでは、TimeHelper.hとTimeHelper.mmのみを追加する。