how to display plain string as date mvc - c#

In my mvc application I have stored my date in string format. eg: 10212013
But I would like to display that sting as a date in my UI eg: 10/21/2013
How to archive this?? Is it possible to user DisplayFormat for this purpose.
EDIT
This is what I need to do.
#Html.DisplayFor(model => DailyTransaction.MyDate)
Datatype of MyDate is string so this will display as 10212013
But I need to display this as 10/21/2013
can I use string format inside the view of MVC project
I tried to use the following and that is also did not work for me.
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public string MyDate{ get; set; }

Try creating a custom DisplayFormatAttribute that will format the string in the correct format. See this How to make configurable DisplayFormat attribute
EDIT: After looking at your question again you could look at using an editor template to display the data: See this: http://blogs.msdn.com/b/nunos/archive/2010/02/08/quick-tips-about-asp-net-mvc-editor-templates.aspx

Use DateTime.ToString() like;
YourDateTime.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture);
For example;
DateTime d = DateTime.Today;
Console.WriteLine(d.ToString("MM/yy/yyyy", CultureInfo.InvariantCulture));
Output will be;
10/21/2013
Here a DEMO.
As an alternative, you can use DisplayFormatAttribute.DataFormatString like;
[DisplayFormat(DataFormatString="{0:MM/yy/yyyy}")]

yeah you just have to use insert function. here is the example
string dateValue = "10212013";
string dateFormat = x.Insert(2, "/");
dateFormat = dateFormat.Insert(5, "/");
thats all...

If you are sure about the saved format of the date you could use Substring() and Format() methods as below:
string.Format("{0}/{1}/{2}", myStringDate.Substring(0,2),
myStringDate.Substring(2,2),
myStringDate.Substring(4))
You can apply this to your Class and here is a demo;
public class myModelClass
{
private string _MyDate;
public string MyDate
{
get {
return string.Format("{0}/{1}/{2}", _MyDate.Substring(0,2),
_MyDate.Substring(2,2),
_MyDate.Substring(4)); }
set { _MyDate = value; }
}
}

You can create custom templates for various data types that are specific to your requirements.
To create a custom template create a new file in /Views/Shared/DisplayTemplates - Call it StringToDate.cshtml. The name is important and is used in the function call below.
Next, in the file add the code to convert the string to a date format as you require. The simplest solution is to insert the / characters.
#model string
if (Model != null && Model.Length == 8)
{
#(Model.Insert(2,"/").Insert(5,"/"))
} else {
#("Err")
}
Add the above to the file and save it. The else part simply outputs an error if the basic format checks fail.
Next in your view, where ever you need to display this value. Simply use
#Html.DisplayFor(model => model.StringDate, "StringToDate")

Related

Handling logic and constants in the View

I have a date that gets displayed on my View that shows the last date a user logged in. They may have never done so. So it's passed as a nullable DateTime.
On the UI, I display it like this:
<td>#(u.LastVisit != null ? u.LastVisit.Value.ToString("dd-MMM-yyyy") : "Not yet")</td>
But I have a few issues with this and think it might be bad practice.
Firstly, the view now has logic. (If null, show "Not Yet", else show the date). The View also dictates the date format. That format is already stored as a constant in a Constants file, accessible from my controller. And the text "Not Yet" should probably be a constant as well.
The only way I can see around this, is to return a String to the UI, and move that logic to the controller. But is that the right way to do this?
You can apply a [DisplayFormat] attribute to the property and set the DataFormatString and NullDisplayText properties, for example
[DisplayFormat(DataFormatString = "{0:dd-MMM-yyyy}", NullDisplayText = "Not yet")]
public DateTime? LastVisit { get; set; }
If you have already defined some constants for the format then you can use (for example) DataFormatString = yourAssembly.Constants.DateFormat where DateFormat is defined as
public const string DateFormat = "{0:dd-MMM-yyyy}";
and in the view use DisplayFor()
#foreach(var u in Model)
{
#Html.DisplayFor(m => u.LastVisit)
}

Convert DateTime to string using another string as a template

I have a string that contains a date & time in some format. For example:
13:53:56 20.08.2014
This string is parsed from a file that user uploads to my service. The exact date & time format is not known. It can change to pretty much any date & time format you know. I do not have a list a expected formats or anything like that.
I want to develop an algorithm that somehow extracts the format from the initial string and applies it to, say, DateTime.Now.
Is there any way to do this simply and elegantly?
If you know the list of expected formats, then define them and use DateTime.TryParseExact() to find out the matching format of your input string. Once you have the matching format, you can simply use the matching format with DateTime.Now.ToString(format).
If this is a web application, perhaps you can "cheat a bit" by sniffing the user's regional settings before they input the string.
The MSDN article "How to: Display Localized Date and Time Information to Web Users" has useful information.
Inspired by a good suggestion by Mani, I've created the following extension method for my needs:
public static bool TryFormatLike(this DateTime dateTime, string another, out string result)
{
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures | CultureTypes.UserCustomCulture | CultureTypes.ReplacementCultures);
foreach (var culture in allCultures)
{
var allPatterns = culture.DateTimeFormat.GetAllDateTimePatterns();
foreach (var pattern in allPatterns)
{
DateTime parsedAnother;
if (DateTime.TryParseExact(another, pattern, culture.DateTimeFormat, DateTimeStyles.AllowWhiteSpaces, out parsedAnother))
{
result = dateTime.ToString(pattern);
return true;
}
}
}
result = string.Empty;
return false;
}
You can use it like that:
string formattedNow;
if (DateTime.Now.TryFormatLike("13.02.2015 16:14:43", out formattedNow))
{
Console.WriteLine(formattedNow);
}
This will print
10.03.2015 23:37:08
Unfortunately, some date & time formats cannot be parsed by all patters in all cultures (for instance, string 16:14:43 13.02.2015 will not be parsed).
Anyway, thank you for your comments & answers. Maybe this method will be helpful to someone.

Textbox for DateTime wrong format

I know this is one of the most frequently asked questions.
I had the solution to this but my current project is driving me nuts.
I use the exact same code and still the result is different.
This is the code I normally use to format my dates:
#Html.TextBoxFor(m => m.DateOfAgenda, "{0:dd/MM/yyyy}")
Normally this should result in 07/10/2014 but for some reason it results in 07-10-2014
When I test it in another project the code above works as expected.
As a test I compared the results of the follow lines:
#Html.TextBoxFor(m => m.DateOfAgenda, "{0:dd/MM/yyyy}")
/* result: 07-10-2014*/
#Html.TextBoxFor(m => m.DateOfAgenda)
/* result: 7-10-2014 00:00:00*/
So my code seems to work partially only the '-' won't be replaced by '/'
Does somebody know how to handle this once and for all?
EDIT
I have custom code setting the Culture.
It uses the route to set it to a specific culture (default is 'nl')
When I put the code below in comments everything seems to work.
But I need this part to load my resources (label text, errors, ...).
var language = handler.RequestContext.RouteData.Values["language"];
if (language != null)
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(language.ToString());
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language.ToString());
}
To be more specific this line breaks the format
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language.ToString());
Does anybody know why? I would expect that {0:dd/MM/yyyy} has priority because it is explicitly set.
Funny part is that the / is just translated to -.
When I use {0:dd//MM//yyyy} it results in 19--10--2014.
EDIT
Sorry for my late response but I couldn't find the time to try this out.
So basically the problem was the culture and my format settings.
#Html.TextBoxFor(m => m.DateOfAgenda, "{0:dd/MM/yyyy}")
The '/' still gets replaced by the divider specified by your culture.
My culture was set to 'nl' but by default this results in 'nl-nl' where they use '-' as date separator. I live in Belgium 'nl-be' and here we use '/'.
The could have set my culture or change the format.
The code below did the trick.
#Html.TextBoxFor(m => m.DateOfAgenda, "{0:dd'/'MM'/'yyyy}")
I'm not that familiar with ASP.NET MVC, but if you don't specify a format, your current culture's DateTimeFormat is used. Also, / is a special format specifier in .NET which means "replace me with the current DateTimeFormats date-separator which seems to be -.
So you should provide CultureInfo.InvariantCulture or mask the format specifier by using \\/instead:
#Html.TextBoxFor(m => m.DateOfAgenda, "{0:dd\\/MM\\/yyyy}")
or by using the character literal '/':
#Html.TextBoxFor(m => m.DateOfAgenda, "{0:dd'/'MM'/'yyyy}")
Read: The "/" Custom Format Specifier
This appears to be by design. TextBoxFor sets the value as per the following code snippet
string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);
which calls the EvalString method of HtmlHelper
internal string EvalString(string key, string format)
{
return Convert.ToString(ViewData.Eval(key, format), CultureInfo.CurrentCulture);
}
which calls the Eval method of ViewDataDictionary
public string Eval(string expression, string format)
{
object value = Eval(expression);
return FormatValueInternal(value, format);
}
internal static string FormatValueInternal(object value, string format)
{
....
return String.Format(CultureInfo.CurrentCulture, format, value);
}
So the value uses the format of the current culture. I presume this is because the DefaultModelBinder use the current culture info to parse the string representation of the date back to a DateTime (if you were able to override it, it would not bind unless you created a custom model binder.
View Page
#Html.TextBoxFor(m => m.DateOfAgenda, new { Value = Model.DateOfAgenda.ToString("dd/MM/yyyy")});
Model page
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime DateOfAgenda{ get; set;}
View Page
#Html.EditorFor(model => model.DateOfAgenda)

replace a JSON date in a string to a more readable date

We want to show some JSON to a user who is testing our application. So we call our REST service in the ASP.NET code behind file and return a string, which holds a lot of JSON.
We then put it in a PRE element in the page, call beautify to create nice readable JSON and all is good: sort of human readable content is shown.
Good but for one thing: all the dates are shown in the normal JSON format like this "/Date(1319266795390+0800)/"
What I want to do is replace those JSON dates with 'normal' dates, in the JSON (C#) string, so in the code behind that is, before I add the string to the PRE element.
I was thinking about some regex, but i couldn't figure out how...
I'v been dealing with dates in JSON string for some time now, there's no standard way for that and which is why there are so many different ways to do it! Maybe it was better if JSON specification could specify an standard format for dates in the first place!
Microsoft is doing it in its own way, counting the msecs since 1970 in UTC format this is something like "/Date(1319266795390+0800)/"
We've been changing the above string to ISO-8601 format ever since using Regular Expressions on top of ASP.Net JavaScriptSerializer output. It is a W3C standard, human readable and the way most browsers serialize Date to string, here's how:
static readonly long DATE1970_TICKS = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
static readonly Regex DATE_SERIALIZATION_REGEX = new Regex(#"\\/Date\((?<ticks>-?\d+)\)\\/", RegexOptions.Compiled);
static string ISO8601Serialization(string input)
{
return DATE_SERIALIZATION_REGEX.Replace(input, match =>
{
var ticks = long.Parse(match.Groups["ticks"].Value) * 10000;
return new DateTime(ticks + DATE1970_TICKS).ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss.fff");
});
}
You can easily change the format to satisfy your needs, to see custom Date and Time formats check out MSDN article here
Here's how it's used:
JavaScriptSerializer ser = new JavaScriptSerializer();
var JsonSrt = ISO8601Serialization(ser.Serialize(DateTime.Now)); // "\"2012-05-09T14:51:38.333\""
Update:
There's an alternative to tweak the JSON string returned from the server in JavaScript to more readable form using Regex:
var str = "/Date(1319266795390+0800)/";
str.replace(/\/Date\((\d+)\+\d+\)\//, function (str, date) {
return new Date(Number(date)).toString();
});
The solution is within the string shown in the question. The JavaScript Date object will parse that format and produce a readable version so Date(1319266795390+0800) returns "Wed Apr 18 2012 08:13:22 GMT-0500 (Central Daylight Time)".
To remove the forward slash from the string you could use the replace function with a regular expression: "/Date(1319266795390+0800)/".replace(/\//g, '').
You can use this:
string date = "/Date(1319266795390+0800)/";
string regex = #"/Date\((.*?)\+(.*?)\)/";
Match match = Regex.Match(date, regex);
DateTime d = new DateTime(1970, 01, 01).AddMilliseconds(long.Parse(match.Result("$1")));
suppose the class you want to serialize looks like this:
public class Something
{
public int ID;
public string Name;
public DateTime Date;
}
change it to:
public class Something
{
public int ID;
public string Name;
public DateTime Date;
public string HumanReadableDate { get { return Date.ToLongDateString(); } }
}
or, if you want that extra property to display only in test enviroment:
public class Something
{
public int ID;
public string Name;
public DateTime Date;
#if DEBUG
public string HumanReadableDate { get { return Date.ToLongDateString(); } }
#endif
}
also, instead of .ToLongDateString() you can use .ToString("yyyy-MM-dd HH:mm") or any other format
Use as regex something like:
(?<= /Date\( )
(?<ticks>[0-9]+)
((?<zonesign>[+-])
(?<zonehour>[0-9]{2})
(?<zoneminutes>[0-9]{2})
)?
(?= \)/ )
This will match the part inside the parentheses of /Date(1319266795390+0800)/. You can then call Regex.Replace on the whole JSON string to replace the numbers with a nicely formatted DateTime:
Use the Match object you get in the match evaluator delegate and extract the ticks, zonesign, zonehour and zoneminutes part, convert it to integers.
Then convert the javascript ticks to .NET ticks (should be *10000), construct the .NET DateTime out of ticks and add/substract the hours and minutes for the time zone.
Convert the DateTime to a string and return it as the replacement.
If your JSON is a serialised representation of a .NET class, maybe you could use the DataContractJsonSerializer to deserialise it on the server, or perhaps you could just define a stub class for your JSON object if you don't need a generic solution to handle multiple datasets:
string json = "{\"Test\": \"This is the content\"}";
DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(TestJson));
var deserialisedContent = ds.ReadObject(new MemoryStream(Encoding.ASCII.GetBytes(json)));
foreach (var field in typeof (TestJson).GetFields())
{
Console.WriteLine("{0}:{1}", field.Name, field.GetValue(deserialisedContent));
}
...
[DataContract]
private class TestJson
{
[DataMember]
public string Test;
}
Use Newtonsoft.JSON. You can provide your own serializers per type, and serialize dates however you want.
http://james.newtonking.com/projects/json-net.aspx
Make a string property for example dateofbirth I am defining here, and return your datetime variable as:
public string DateOfBirthString
{
get { return DateOfBirth.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss"); }
set { DateOfBirth = string.IsNullOrEmpty(value) ? new DateTime(1900, 1, 1) : Convert.ToDateTime(value); }
}
because this will return string so it will be same at client side so and aslo take string dateTime from user and convert it.
string input = [yourjsonstring];
MatchEvaluator me = new MatchEvaluator(MTListServicePage.MatchDate);
string json = Regex.Replace(input, "\\\\/\\Date[(](-?\\d+)[)]\\\\/", me, RegexOptions.None)

Convert DateTime with TypeDescriptor.GetConverter.ConvertFromString (using custom format)

Is there any way to make
TypeDescriptor.GetConverter.ConvertFromString convert to DateTime using a custom format e.g. "2011-04-21 13-03-56"?
If not, is there any DateTime-format out there that can be applied to a folder name (/,\,:,etc. are not allowed as you know)?
Help is very much appreciated. Thanks in advance
Random-I-Am
Edit:
Since my request still seems to not be understood correctly I am again trying to elaborate on my question. My users are creating folders with specific names. For example "1000_Link_Topic1_2011-01-25 14-12-10". They are free to combine their information as they like and omit information where needed. They don't even have to care about case sensitivity. So I could face another folder named "1000_link_Topic2".
What I have is a single class with a single property for each possible fragment of information. In this case I would have (Since I had to find a way of checking each properties default value regardless of the property type I am using nullable types):
Short? short_val;
EContentType? enum_val;
String string_val;
DateTime? datetime_val;
My code obviously splits the folder name at "_" and then tells for each fragment to which of the above property types it belongs. As soon as I know the corresponding type I am trying to convert to the Type, lets say t, using TypeDescriptor.GetConverter(t).ConvertFromString(info_frag[i]). I hope you now understand why I cannot use another conversion Method.
The code works for all the types mentioned above. My problem is to find a custom DateTime format that can be used on a folder name. All of the formats I know are using colons to separate hours from minutes and seconds.
What I want is a way to convert from a custom DateTime-format to a DateTime-object using TypeDescriptor.GetConverter.ConvertFromString. If that is not possible I either need to find a standard DateTime-format which can be assigned as a folder name without any further conversion or somehow extend the built-in DateTime-formats by my custom format. If it is going to be the latter I do not care about being able to use seconds or minutes. Hours will do the job.
Thanks again for being as patient as you are and helping me out with this one. Feel free to ask as many further questions as you like. I hope you can help me getting this one to work.
Random-I-Am
I have looked into your problem a little and found that the standard DateTimeTypeConverter uses DateTime.Parse internally which doesn't listen to CurrentCulture info at all. Instead you can trick the conversion process with your own TypeConverter!
I do not know how to attach the new typeconverter to the existing DateTime structure, if you even can, so I made a miniture AdvancedDateTime structure .. which is empty. Noone said your custom TypeConvert should even return such a thing! This one returns a regular DateTime. I provided the code below:
public class CustomDateTimeTypeConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return DateTime.ParseExact(value.ToString(), "yyyy-MM-dd HH-mm-ss", culture);
}
}
[TypeConverter(typeof(CustomDateTimeTypeConverter))]
struct AdvancedDateTime
{
}
[TestFixture]
public class DateTime
{
[Test]
public void TypeConvert_StrangeFormat_ConvertsWithoutProblem()
{
string datetime = "2011-04-21 23-12-13";
TypeConverter converter = TypeDescriptor.GetConverter( typeof (AdvancedDateTime) );
var convertedFromString = converter.ConvertFromString(datetime);
Assert.AreEqual(new DateTime(2011,4,21, 23,12,13), convertedFromString);
}
}
Try this
string m_strDate = DateTime.Now.ToString("MM/dd/yyyy");
m_strDate = m_strDate.Replace("/", "");
Append this m_strDate to your folder
A sample i used for text file is as follows
strPath += "/FileHeader_" + m_strDate + ".txt";
Check this sample
DateTime dt=new DateTime(1990,5,6);
Console.WriteLine(TypeDescriptor.GetConverter(dt).ConvertTo(dt, typeof(string)));
string myStr="1991-10-10";
Console.WriteLine(TypeDescriptor.GetConverter(dt).ConvertFrom(myStr));
The sample code i written just to display as per you need try as per your requirement
string s = "Folder";
DateTime dt = new DateTime(1990, 5, 6);
string str = TypeDescriptor.GetConverter(dt).ConvertTo(dt, typeof(string)).ToString();
string myStr = "1991-10-10";
string str1 = TypeDescriptor.GetConverter(dt).ConvertFrom(myStr).ToString();
s = s + str1.Replace("/", "").Replace(":", "");
textBox1.Text = s;

Categories

Resources