none
Azureにデプロイすると日付の値がローカルと異なる。(洋風?になる。) RRS feed

  • 質問

  • こんにちは。ASP.net開発二週間の初心者Kです。

    Visual Studio 2013.4 + ASP.net + VB.net + Azure SQL→Azureにデプロイ で開発しております。

    表題にもありますように、アプリケーションをAzureにデプロイすると日付の値がローカルと異なってしまいます。(洋風?になる。)

    http://localhost/では、下記の様に表示されるものが(これは意図ととして正しい。)
    ・LinkButton1→2014年11月26日(水曜日) 
    ・Label1→2014/11/26 0:00:00 

    azurewebsites.netにデプロイすると、下記の様に、何やら洋風になってしまいます。。。
    ・LinkButton1→2014年11月25日(Tuesday) (水曜日が→Tuesdayになる。)
    ・Label1→11/25/2014 12:00:00 AM (*月-日-年の順になる。)


    多分、Azure側か、VisualStudio側で何かしらの設定が必要だと思うのですが、私の技量では分かりませんでした。。。


    お知恵のある方、お力添え頂けると幸いです。

    念のため、コードも記載します。
    Dim dtToday As DateTime = DateTime.Today
    Dim strDate As String = DateTime.Now.ToString("yyyy年MM月dd日(dddd)") 
    LinkButton1.Text = strDate


    Dim dtToday2 As DateTime = DateTime.Today
    Dim dt1 As DateTime
     dt1 = DateTime.Today
    Label1.Text = dt1.ToString

    2014年11月25日 22:58

回答

  • すでに解決済みマークがついていますが、解決方法が気になるので一言・・・

    > web.configの<system.web>の下に、
    > <globalization uiCulture="ja" culture="ja-JP" />
    > を追記することで修正できました。

    そうすると Web アプリ全体が ja-JP カルチャ専用になってしまい、せっかくグローバル化されて多言語対応ができるようになっている .NET アプリの機能を自ら殺してしまうことになります。

    質問者さんのケースでは ja-JP 固定で良いのかもしれませんが、それでも以下に述べることは知っておいたほうが良いと思って、レスします。

    Culture, UICulture の値として "auto" を設定した場合には(ja-JP とか en-US ではなくて)、ブラウザが要求に含めて送信してくる Accept-Language ヘッダの内容を ASP.NET が見て自動的にカルチャを特定してくれます。

    Accept-Language ヘッダの内容は、ブラウザの言語設定によります。

    例えば、IE なら[ツール(T)]⇒[インターネットオプション(O)]⇒[全般]タブで[言語(L)]ボタンをクリック ⇒「言語の優先順位」ダイアログで設定できます。

    IE の言語の優先順位の設定

    「言語の優先順位」の設定で、例えば ja-JP, en-US, fr-FR の順になっているとすれば、Accept-Language ヘッダにもその順序で設定されます。

    そうすると、ASP.NET は現在のスレッドのカルチャを ja-JP と判断し、DateTime.Now.ToString("yyyy年MM月dd日(dddd)") は "2014年11月26日(水曜日)" に、DateTime.Today.ToString() は "2014/11/26 0:00:00" というように日本語形式なるはずです。

    「言語の優先順位」の設定の順序を変えて、例えば en-US を一番上に持ってくると、質問者さんが「azurewebsites.netにデプロイ」したときと同じ米国形式になるはずです。

    下にアップしたサンプルコードで試すと、「言語の優先順位」の設定の順序を変えると、日付の表示もそれに対応して以下のように変わるはずです。

    CurrentCulture: ja-JP
    --------------------------
    2014年11月26日(水曜日)
    2014/11/26 0:00:00


    CurrentCulture: en-US
    ---------------------------
    2014年11月26日(Wednesday)
    11/26/2014 12:00:00 AM


    CurrentCulture: fr-FR
    ---------------------------
    2014年11月26日(mercredi)
    26/11/2014 00:00:00

    uiCulture, culture 属性は、web.config でなくても、下の例のように @Page ディレクティブで設定し、そのページのみに適用することもできます。どちらで設定するにせよ、"auto" に設定するのを忘れると、ブラウザの言語指定による自動切り替えは行われないので注意してください。

    <%@ Page Language="C#" Culture="auto" UICulture="auto" %>
    <%@ Import Namespace="System.Threading" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
    
        protected void Page_Load(object sender, EventArgs e)
        {
            Label1.Text = "CurrentCulture: " +
            Thread.CurrentThread.CurrentCulture.ToString();
    
            LinkButton1.Text = 
                DateTime.Now.ToString("yyyy年MM月dd日(dddd)");
            
            Label2.Text = DateTime.Today.ToString();
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server" />
            <hr />
            <asp:LinkButton ID="LinkButton1" runat="server" />
            <br />
            <asp:Label ID="Label2" runat="server" />
        </div>
        </form>
    </body>
    </html>

    なお、時差の対応はまた別の話ですので注意してください。
    • 編集済み SurferOnWww 2014年11月26日 3:43 一部訂正
    • 回答としてマーク kan.net 2014年11月26日 5:40
    2014年11月26日 3:41
  • ASP.NETではglobalizationという言語に合わせて書式などを切り替える機能があります。既定ではOSの言語が使われます。このため日本語OSを使用したローカル環境と英語OSを使用したAzure環境で異なる結果となっています。

    方法 : ASP.NET Web ページのグローバリゼーション用のカルチャおよび UI カルチャを設定するに設定方法が説明されています。

    • 回答としてマーク kan.net 2014年11月25日 23:53
    2014年11月25日 23:25
  • AzureはUTC(日本時間の-9時間)で動作しており、SQL Databaseも同様です。
    そのため、SQL Databaseでgetdateなどで日付・時刻を取得する場合もUTCで取得されますのでご注意ください。
    • 回答としてマーク kan.net 2014年11月26日 5:41
    2014年11月26日 1:41
  • そうですね、私の回答では書式だけで時差について言及できていませんでした。

    DateTime.Nowなどのローカル時間情報はそのマシンのタイムゾーン設定に依存します。依存せずに日本標準時を得る方法ですが、

    var jst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
    var localTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, jst);
    

    C#で申し訳ありませんがこのようなコードになります。"Tokyo Standard Time"がWindowsに於ける日本標準時を表す固定文字列です。(日本の場合はあまり関係ありませんが)夏時間などを考慮した現在時刻を得られます。

    • 回答としてマーク kan.net 2014年11月26日 5:41
    2014年11月26日 2:12

すべての返信

  • ASP.NETではglobalizationという言語に合わせて書式などを切り替える機能があります。既定ではOSの言語が使われます。このため日本語OSを使用したローカル環境と英語OSを使用したAzure環境で異なる結果となっています。

    方法 : ASP.NET Web ページのグローバリゼーション用のカルチャおよび UI カルチャを設定するに設定方法が説明されています。

    • 回答としてマーク kan.net 2014年11月25日 23:53
    2014年11月25日 23:25
  • 佐祐理さん、度々素早いご対応ありがとうございます!!

    web.configの<system.web>の下に、
    <globalization uiCulture="ja" culture="ja-JP" />

    を追記することで修正できました。

    「Azure 日付 変わる」「Azure 日付 英語表記」などで検索しても見つからなかったのですが、今回「カルチャ、UIカルチャ」というものがあることを学びました。

    ありがとうございました!!

    m(__)m
    2014年11月25日 23:53
  • AzureはUTC(日本時間の-9時間)で動作しており、SQL Databaseも同様です。
    そのため、SQL Databaseでgetdateなどで日付・時刻を取得する場合もUTCで取得されますのでご注意ください。
    • 回答としてマーク kan.net 2014年11月26日 5:41
    2014年11月26日 1:41
  • そうですね、私の回答では書式だけで時差について言及できていませんでした。

    DateTime.Nowなどのローカル時間情報はそのマシンのタイムゾーン設定に依存します。依存せずに日本標準時を得る方法ですが、

    var jst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
    var localTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, jst);
    

    C#で申し訳ありませんがこのようなコードになります。"Tokyo Standard Time"がWindowsに於ける日本標準時を表す固定文字列です。(日本の場合はあまり関係ありませんが)夏時間などを考慮した現在時刻を得られます。

    • 回答としてマーク kan.net 2014年11月26日 5:41
    2014年11月26日 2:12
  • すでに解決済みマークがついていますが、解決方法が気になるので一言・・・

    > web.configの<system.web>の下に、
    > <globalization uiCulture="ja" culture="ja-JP" />
    > を追記することで修正できました。

    そうすると Web アプリ全体が ja-JP カルチャ専用になってしまい、せっかくグローバル化されて多言語対応ができるようになっている .NET アプリの機能を自ら殺してしまうことになります。

    質問者さんのケースでは ja-JP 固定で良いのかもしれませんが、それでも以下に述べることは知っておいたほうが良いと思って、レスします。

    Culture, UICulture の値として "auto" を設定した場合には(ja-JP とか en-US ではなくて)、ブラウザが要求に含めて送信してくる Accept-Language ヘッダの内容を ASP.NET が見て自動的にカルチャを特定してくれます。

    Accept-Language ヘッダの内容は、ブラウザの言語設定によります。

    例えば、IE なら[ツール(T)]⇒[インターネットオプション(O)]⇒[全般]タブで[言語(L)]ボタンをクリック ⇒「言語の優先順位」ダイアログで設定できます。

    IE の言語の優先順位の設定

    「言語の優先順位」の設定で、例えば ja-JP, en-US, fr-FR の順になっているとすれば、Accept-Language ヘッダにもその順序で設定されます。

    そうすると、ASP.NET は現在のスレッドのカルチャを ja-JP と判断し、DateTime.Now.ToString("yyyy年MM月dd日(dddd)") は "2014年11月26日(水曜日)" に、DateTime.Today.ToString() は "2014/11/26 0:00:00" というように日本語形式なるはずです。

    「言語の優先順位」の設定の順序を変えて、例えば en-US を一番上に持ってくると、質問者さんが「azurewebsites.netにデプロイ」したときと同じ米国形式になるはずです。

    下にアップしたサンプルコードで試すと、「言語の優先順位」の設定の順序を変えると、日付の表示もそれに対応して以下のように変わるはずです。

    CurrentCulture: ja-JP
    --------------------------
    2014年11月26日(水曜日)
    2014/11/26 0:00:00


    CurrentCulture: en-US
    ---------------------------
    2014年11月26日(Wednesday)
    11/26/2014 12:00:00 AM


    CurrentCulture: fr-FR
    ---------------------------
    2014年11月26日(mercredi)
    26/11/2014 00:00:00

    uiCulture, culture 属性は、web.config でなくても、下の例のように @Page ディレクティブで設定し、そのページのみに適用することもできます。どちらで設定するにせよ、"auto" に設定するのを忘れると、ブラウザの言語指定による自動切り替えは行われないので注意してください。

    <%@ Page Language="C#" Culture="auto" UICulture="auto" %>
    <%@ Import Namespace="System.Threading" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
    
        protected void Page_Load(object sender, EventArgs e)
        {
            Label1.Text = "CurrentCulture: " +
            Thread.CurrentThread.CurrentCulture.ToString();
    
            LinkButton1.Text = 
                DateTime.Now.ToString("yyyy年MM月dd日(dddd)");
            
            Label2.Text = DateTime.Today.ToString();
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server" />
            <hr />
            <asp:LinkButton ID="LinkButton1" runat="server" />
            <br />
            <asp:Label ID="Label2" runat="server" />
        </div>
        </form>
    </body>
    </html>

    なお、時差の対応はまた別の話ですので注意してください。
    • 編集済み SurferOnWww 2014年11月26日 3:43 一部訂正
    • 回答としてマーク kan.net 2014年11月26日 5:40
    2014年11月26日 3:41
  • 佐祐理様、r-cap様、SurferOnWww様

    問題解決したにも関わらず、事象を深く掘り下げて頂いてありがとうございます!

    Azure利用時における「時間」の取り扱いについて、下記を理解いたしました。ありがとうございました!!


    1)
    今回の私の場合、は日本での使用のみなので、

    <globalization uiCulture="ja" culture="ja-JP" />で問題ないが、

    WEBアプリケーションをグローバルに展開したい場合は

    <globalization uiCulture="auto" culture="auto" />

    が適している。(というより、上記にしておくのがベター)

    2)
    「DateTime.Nowなどのローカル時間情報はそのマシンのタイムゾーン設定に依存」するため、WEBアプリケーションのクライアントに他のタイムゾーンに設定しているPCがある場合等、、妙な挙動となる。

    3)
    UTCやJSTを意識して開発する必要がある。例えば、today.nowなどで取得される日付はUTCとなるため、時差が生じる。そのため、下記の様なコードにする必要がある。

    Dim jst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time")
    Dim localTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, jst)

    label1.text = localTime.ToString("yyyy年MM月dd日(dddd)")



    • 編集済み kan.net 2014年11月27日 1:11 修正
    2014年11月26日 5:40
  • SurferOnWwwさんのアドバイスに補足などいろいろ…

    私の紹介したページにももちろんこの辺りのことにも言及されています。ただその中でも1点気になる記述があり

    ブラウザ設定のみに基づいてページの UI カルチャを決定することはお勧めしません。これは、ユーザーがそのユーザー用に設定されていないブラウザ (たとえば、インターネット カフェ) を使用することがよくあるためです。

    とあります。無条件に uiCilture="auto" が推奨されるわけではなくよく判断してください。
    # 実際、MicrosoftやGoogleなど大手サイトを見ていると英語設定のブラウザーからアクセスしていても日本語コンテンツが返されます。IPアドレスによる判断なのかなぁ?

    また、グローバル展開を考慮したサイトはなかなか骨が折れます。SurferOnWwwさんは理解した上で書かれていると思いますが、

    Label1.Text = "CurrentCulture: " + Thread.CurrentThread.CurrentCulture.ToString();

    というような文字列を + (VBにおける&)結合は許されません。その上で、質問者さんは DateTime.Now.ToString("yyyy年MM月dd日(dddd)")  といったコードを試している辺り、日本語オンリーだろうなという予想の元、あえてグローバリゼーションについて説明しませんでした。

    2014年11月26日 7:01
  • Label1.Text = "CurrentCulture: " + Thread.CurrentThread.CurrentCulture.ToString();

    というような文字列を + (VBにおける&)結合は許されません。


    その理由を詳しく教えていただけませんか?
    2014年11月26日 7:35
  • 佐祐理さん、ご返答ありがとうございます。

    おっしゃるように、私のユーザーは日本人がせいぜい20名程度ですので、頂いた解答で十分でした。ありがとうございました。

    また、r-cap様、SurferOnWww様のご指摘により、今後の開発時にハマる要素を洗い出しできました。ありがとうございました。

    必要に駆られて、約15年ぶりにプログラミング(VB6世代)しましたが、

    Visual Studio 2013.4 + ASP.net + VB.net + Azure SQL→Azure

    という環境であればこんなにあっさりWEBアプリケーションを開発できるのかと、隔世の感があります。

    初心者じみた質問ばかりで申し訳ありません。皆様、今後ともよろしくお願いいたします。


    2014年11月26日 7:51
  • 一般論としては推奨される国際対応アプリケーション開発手順なんかにも説明があります。

    推奨されるローカリゼーション手順
    4. 文字列を実行時に連結して使う方法は避けてください。 連結される文字列は、英語の語順に依存することが多く、ほかの言語でのローカライズ作業が困難になります。

    です。

    今回の場合、ラベルですし大丈夫だろうという判断もあるかもしれませんが、ラベルはラベルでHTML側に埋め込まれて、HTML側でのローカライズを受けるべきですし…。まぁややこしいです。

    2014年11月26日 8:47
  • レスを有難うございます。

    ただ、そこに書いてあることは私がアップしたコードでは問題なさそうです。

    例えば、検索機能があって、それに xxxx を言う文字列を入力して検索をかけ、結果を表示するページのどこかに、

    Search results for 'xxxx'

    と表示されるようになっている場合を考えます。en-US の場合 "Search results for" という文字列をリソースファイルより取得し、xxxx をユーザ入力から取得して、"Search results for" + " " +  "'xxxx'" と文字連結しているとします。

    そうすると、ja-JP でリソースファイルから取得できる文字列が "の検索結果" というような場合、連結して表示される文字列は、

    の検索結果 'xxxx'

    となってしまうのでうまくない・・・ということだと思います。


    • 編集済み SurferOnWww 2014年11月26日 10:05 誤字訂正
    2014年11月26日 9:54