Flex3 で strftime

Flex3 で任意の形式での日付のフォーマットを行うには DateFormatter というクラスを使います。

http://livedocs.adobe.com/flex/3_jp/langref/mx/formatters/DateFormatter.html

リンク先を見ての通り new した段階で formatString を渡せないため、どうしても使い勝手の悪さは否めません。何とかしようとした結果がこれだよ!

package
{
  import mx.formatters.DateFormatter;

  public class DateUtil {
    private static const ONE_DAY_MILLISEC:int = 24 * 60 * 60 * 1000;

    public static function strftime(date:*, format:String = "MM/DD/YYYY"):String {
      var result:String;
      var regExpArray:Array = [
        {pattern: /%A/g, str: "EEEE"},
        {pattern: /%a/g, str: "EEE"},
        {pattern: /%B/g, str: "MMMM"},
        {pattern: /%b/g, str: "MMM"},
        {pattern: /%c/g, str: "EEEE MMMM DD J:NN:SS YYYY"},
        {pattern: /%d/g, str: "DD"},
        {pattern: /%H/g, str: "J"},
        {pattern: /%I/g, str: "L"},
        {pattern: /%j/g, str: totalDay(date)},
        {pattern: /%M/g, str: "NN"},
        {pattern: /%m/g, str: "MM"},
        {pattern: /%p/g, str: "A"},
        {pattern: /%S/g, str: "SS"},
        {pattern: /%U/g, str: weekNum(date, 0)},
        {pattern: /%W/g, str: weekNum(date, 1)},
        {pattern: /%w/g, str: String(date.day)},
        {pattern: /%X/g, str: "J:NN:SS"},
        {pattern: /%x/g, str: "MM/DD/YY"},
        {pattern: /%Y/g, str: "YYYY"},
        {pattern: /%y/g, str: "YY"}
      ];

      if(date is Date || date is String) {
        var formatter:DateFormatter = new DateFormatter();
        for each(var obj:Object in regExpArray) {
          format = format.replace(obj["pattern"], obj["str"])
        }

        formatter.formatString = format;
        if(/[A-Z]/.test(format)) {
          result = formatter.format(date);
        }
        else {
          result = format;
        }
      }
      else {
        result = "invalid Class"
      }

      return result;
    }

    private static function totalDay(_date:*):String {
      var today:Date = _date is Date ? _date : new Date(_date);
      var startOfYear:Date = new Date(today.fullYear, 0, 1);

      return String(int((today.time - startOfYear.time) / ONE_DAY_MILLISEC) + 1);
    }

    private static function weekNum(_date:*, day:int):String {
      var today:Date = _date is Date ? _date : new Date(_date);
      var startOfYear:Date = new Date(today.fullYear, 0, 1);
      var result:String;

      while(startOfYear.day == day) {
        startOfYear.date += 1;
      }
      if(startOfYear > today) {
        result = "0";
      }
      else {
        result = String(int(int((today.time - startOfYear.time) / ONE_DAY_MILLISEC) / 7) + 1);
      }

      return result;
    }
  }
}

これを DateUtil.as などとネーミングして呼び出します。使い方はこんな感じ。

var date:Date = new Date();
DateUtil.strftime(date, "%Y-%m-%d");

結局は DateFormatter を呼んでいるだけなので大差ありませんが、多少書くときに楽なんじゃないかなあ、と。なお、フォーマット文字列は Ruby 準拠ですが、タイムゾーンは取得できるのか分からないので保留しました。
また DateFormatter の仕様か "%c %c" のように同じフォーマット文字を複数回使おうとすると値が正しく返らなくなるようです(なので、正規表現のグローバルフラグも実は意味なし)。
ついでに、やっていて分かったのですがフォーマット可能な文字列が存在しない場合 DateFormatter.format は空の文字列を返す様子。怪しい分岐はそのための処理です。