2009-01-31 32 views
43

Tôi có định dạng Ngày giờ tùy chỉnh bao gồm trình chỉ định AM/PM, nhưng tôi muốn chữ "AM" hoặc "PM" là chữ thường làm cho phần còn lại của ký tự chữ thường.Nhận AM/PM trong một ngày bằng chữ thường chỉ sử dụng định dạng ngày giờ

Điều này có thể sử dụng một định dạng duy nhất và không sử dụng regex không?

Đây là những gì tôi đã có ngay bây giờ:

item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt") 

Một ví dụ về đầu ra ngay bây giờ sẽ là Thứ bảy 31 Tháng 1, 2009 tại 1:34

+0

thêm tại http://stackoverflow.com/questions/448634/how-to-format-a-datetime-like-oct-10-2008-1043am-cst-in-c – tvanfosson

Trả lời

57

Cá nhân tôi sẽ định dạng nó trong hai phần: phần không sáng/chiều, và sáng/chiều phần với ToLower:

string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mm") + 
        item.PostedOn.ToString("tt").ToLower(); 

Một tùy chọn khác (mà tôi sẽ điều tra trong một giây) là để lấy DateTimeFormatInfo hiện tại, tạo một bản sao và thiết lập các trình thiết kế am/pm cho phiên bản chữ thường. Sau đó, sử dụng thông tin định dạng đó cho định dạng thông thường. Bạn muốn cache DateTimeFormatInfo, rõ ràng là ...

EDIT: Mặc dù nhận xét của tôi, tôi đã viết bit bộ nhớ đệm anyway. Nó có thể sẽ không được nhanh so với mã trên (vì nó liên quan đến một khóa và một tra cứu từ điển) nhưng nó làm cho mã gọi đơn giản hơn:

string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", 
              GetLowerCaseInfo()); 

Dưới đây là một chương trình đầy đủ để chứng minh:

using System; 
using System.Collections.Generic; 
using System.Globalization; 

public class Test 
{ 
    static void Main() 
    { 
     Console.WriteLine(DateTime.Now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", 
               GetLowerCaseInfo()); 
    } 

    private static readonly Dictionary<DateTimeFormatInfo,DateTimeFormatInfo> cache = 
     new Dictionary<DateTimeFormatInfo,DateTimeFormatInfo>(); 

    private static object cacheLock = new object(); 

    public static DateTimeFormatInfo GetLowerCaseInfo() 
    { 
     DateTimeFormatInfo current = CultureInfo.CurrentCulture.DateTimeFormat; 
     lock (cacheLock) 
     { 
      DateTimeFormatInfo ret; 
      if (!cache.TryGetValue(current, out ret)) 
      { 
       ret = (DateTimeFormatInfo) current.Clone(); 
       ret.AMDesignator = ret.AMDesignator.ToLower(); 
       ret.PMDesignator = ret.PMDesignator.ToLower(); 
       cache[current] = ret; 
      } 
      return ret; 
     } 
    } 
} 
+0

Tôi thích cái này tốt hơn bất cứ thứ gì được đăng trong câu hỏi khác ... cảm ơn! –

+0

Mã được đăng hoặc ý tưởng của một DateTimeFormatInfo mới? Nếu đó là sau này, tôi sẽ đưa ra một số mã cho bạn. Nếu nó là cũ, tôi sẽ không bận tâm :) DateTimeFormatInfo.Clone() có lẽ là con đường phía trước mặc dù. –

+0

Các cựu - sau này, trong khi cực kỳ tuyệt vời, là waaaay overkill trong trường hợp này. –

1

EDIT: Jon Ví dụ là tốt hơn nhiều, mặc dù tôi nghĩ rằng phương pháp mở rộng vẫn là con đường để đi, do đó bạn không cần phải lặp lại mã ở khắp mọi nơi. Tôi đã gỡ bỏ thay thế và thay thế ví dụ đầu tiên của Jon tại chỗ trong phương pháp mở rộng. Ứng dụng của tôi thường là ứng dụng mạng nội bộ và tôi không phải lo lắng về nền văn hóa không phải của Hoa Kỳ.

Thêm phương thức tiện ích mở rộng để thực hiện việc này cho bạn.

public static class DateTimeExtensions 
{ 
    public static string MyDateFormat(this DateTime dateTime) 
    { 
     return dateTime.ToString("dddd, MMMM d, yyyy a\\t h:mm") + 
       dateTime.ToString("tt").ToLower(); 
    } 
} 

... 

item.PostedOn.MyDateFormat(); 

EDIT: ý tưởng khác về cách để làm điều này tại How to format a DateTime like "Oct. 10, 2008 10:43am CST" in C#.

+0

Maaaan đó là chính xác những gì tôi đã hy vọng để tránh: ( –

+0

Nó cũng không làm việc cho các nền văn hóa với một AM/PM chỉ định khác hơn AM/PM. –

+0

Những gì Jon nói và có tiềm năng để bork trong một miền địa phương nơi AM được coi là một phần tên của ngày (không chắc, nhưng vẫn còn xấu từ POV đúng) Tốt hơn là sử dụng một định dạng riêng cho phần am/pm, ToLower(), và nối thêm nó vào – Mark

18

Bạn có thể chia chuỗi định dạng thành hai phần, và sau đó thành chữ thường AM/PM phần, như vậy:

DateTime now = DateTime.Now; 
string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mm"); 
nowString = nowString + now.ToString("tt").ToLower(); 

Tuy nhiên, tôi nghĩ rằng càng el giải pháp egant là sử dụng một DateTimeFormatInfo instance mà bạn xây dựng và thay thế AMDesignatorPMDesignator tính với "sáng" và "tối" tương ứng:

DateTimeFormatInfo fi = new DateTimeFormatInfo(); 

fi.AMDesignator = "am"; 
fi.PMDesignator = "pm"; 

string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", fi); 

Bạn có thể sử dụng các ví dụ DateTimeFormatInfo để tùy chỉnh nhiều khía cạnh khác của việc chuyển đổi một DateTime để a string.

+0

Tôi thích phương pháp này vì biến "hiện tại" không có sẵn cho tôi - tôi có biểu thức DataBind phức tạp trông sẽ xấu xí và điều này sẽ xử lý tất cả trong một cuộc gọi hàm. – umbyersw

+1

Tôi thích phương pháp DateTimeFormatInfo, đặc biệt là vì chúng tôi có một số trường hợp chúng tôi muốn hiển thị "a.m." và "p.m." (bao gồm cả các giai đoạn), làm cho giải pháp ToLower() trở nên lộn xộn hơn rất nhiều. – JackAce

+0

Hoặc đơn giản là 'now.ToString (" dddd, MMMM d, yyyy a \\ t h: mmtt ", mới DateTimeFormatInfo {AMDesignator =" am ", PMDesignator =" pm "});' –

1

Vấn đề với các cách tiếp cận trên là lý do chính bạn sử dụng chuỗi định dạng là bật tính năng bản địa hóa và các phương pháp được đưa ra cho đến giờ sẽ phá vỡ bất kỳ quốc gia hoặc văn hóa nào không muốn bao gồm am hoặc pm cuối cùng.Vì vậy, những gì tôi đã làm được viết ra một phương pháp mở rộng hiểu một chuỗi định dạng bổ sung 'TT' có nghĩa là một chữ thường am/pm. Mã bên dưới được gỡ rối cho các trường hợp của tôi, nhưng có thể chưa hoàn hảo:

/// <summary> 
    /// Converts the value of the current System.DateTime object to its equivalent string representation using the specified format. The format has extensions over C#s ordinary format string 
    /// </summary> 
    /// <param name="dt">this DateTime object</param> 
    /// <param name="formatex">A DateTime format string, with special new abilities, such as TT being a lowercase version of 'tt'</param> 
    /// <returns>A string representation of value of the current System.DateTime object as specified by format.</returns> 
    public static string ToStringEx(this DateTime dt, string formatex) 
    { 
     string ret; 
     if (!String.IsNullOrEmpty(formatex)) 
     { 
      ret = ""; 
      string[] formatParts = formatex.Split(new[] { "TT" }, StringSplitOptions.None); 
      for (int i = 0; i < formatParts.Length; i++) 
      { 
       if (i > 0) 
       { 
        //since 'TT' is being used as the seperator sequence, insert lowercase AM or PM as appropriate 
        ret += dt.ToString("tt").ToLower(); 
       } 
       string formatPart = formatParts[i]; 
       if (!String.IsNullOrEmpty(formatPart)) 
       { 
        ret += dt.ToString(formatPart); 
       } 
      } 
     } 
     else 
     { 
      ret = dt.ToString(formatex); 
     } 
     return ret; 
    } 
0

Đây sẽ là hiệu suất tốt nhất trong số tất cả các tùy chọn này. Nhưng quá xấu họ không thể làm việc trong một tùy chọn chữ thường vào định dạng DateTime (tt đối diện TT?). Thông tin

public static string AmPm(this DateTime dt, bool lower = true) 
    { 
     return dt.Hour < 12 
      ? (lower ? "am" : "AM") 
      : (lower ? "pm" : "PM"); 
    } 
Các vấn đề liên quan