Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jalaali (Persian) Date input support #1205

Open
wants to merge 4 commits into
base: v1_develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 67 additions & 12 deletions Terminal.Gui/Views/DateField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
//
// Licensed under the MIT license
//
using NStack;
using System;
using System.Globalization;
using System.Linq;
using NStack;

namespace Terminal.Gui {
/// <summary>
Expand All @@ -25,6 +25,7 @@ public class DateField : TextField {
string sepChar;
string longFormat;
string shortFormat;
bool isJalaali;

int FieldLen { get { return isShort ? shortFieldLen : longFieldLen; } }
string Format { get { return isShort ? shortFormat : longFormat; } }
Expand All @@ -47,9 +48,11 @@ public class DateField : TextField {
/// <param name="y">The y coordinate.</param>
/// <param name="date">Initial date contents.</param>
/// <param name="isShort">If true, shows only two digits for the year.</param>
public DateField (int x, int y, DateTime date, bool isShort = false) : base (x, y, isShort ? 10 : 12, "")
/// <param name="isJalaali">If true, parse will convert jalaali input fo georgian date</param>
public DateField (int x, int y, DateTime date, bool isShort = false, bool isJalaali = false) : base (x, y, isShort ? 10 : 12, "")
tig marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few unit tests that prove the various constructors work as they should would be good.

{
this.isShort = isShort;
this.isJalaali = isJalaali;
Initialize (date);
}

Expand All @@ -62,9 +65,13 @@ public DateField () : this (DateTime.MinValue) { }
/// Initializes a new instance of <see cref="DateField"/> using <see cref="LayoutStyle.Computed"/> layout.
/// </summary>
/// <param name="date"></param>
public DateField (DateTime date) : base ("")
/// <param name="isJalaali"></param>
public DateField (DateTime date, bool isJalaali = false) : base ("")
{
this.isShort = true;

this.isJalaali = isJalaali;
if (!isJalaali)
this.isShort = true;
Width = FieldLen + 2;
Initialize (date);
}
Expand All @@ -73,8 +80,8 @@ void Initialize (DateTime date)
{
CultureInfo cultureInfo = CultureInfo.CurrentCulture;
sepChar = cultureInfo.DateTimeFormat.DateSeparator;
longFormat = GetLongFormat (cultureInfo.DateTimeFormat.ShortDatePattern);
shortFormat = GetShortFormat (longFormat);
longFormat = isJalaali ? $" yyyy{sepChar}MM{sepChar}dd" : GetLongFormat (cultureInfo.DateTimeFormat.ShortDatePattern);
shortFormat = isJalaali ? $" yy{sepChar}MM{sepChar}dd" : GetShortFormat (longFormat);
CursorPosition = 1;
Date = date;
TextChanged += DateField_Changed;
Expand All @@ -83,8 +90,10 @@ void Initialize (DateTime date)
void DateField_Changed (ustring e)
{
try {

if (!DateTime.TryParseExact (GetDate (Text).ToString (), GetInvarianteFormat (), CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result))
Text = e;

} catch (Exception) {
Text = e;
}
Expand Down Expand Up @@ -129,14 +138,21 @@ public DateTime Date {

var oldData = date;
date = value;
this.Text = value.ToString (Format);
if (isJalaali) {

this.Text = ToJalaaliString (Format, date);
} else {
this.Text = value.ToString (Format);
}
var args = new DateTimeEventArgs<DateTime> (oldData, value, Format);
if (oldData != value) {
OnDateChanged (args);
}
}
}



/// <summary>
/// Get or set the date format for the widget.
/// </summary>
Expand Down Expand Up @@ -202,11 +218,28 @@ bool SetText (ustring text)
vals [idx] = day.ToString ();
} else
day = Int32.Parse (vals [idx].ToString ());
string d = GetDate (month, day, year, frm);
DateTime result;
if (isJalaali) {
try {
PersianCalendar pc = new PersianCalendar ();
if (year < 10) {
year += 1400;
}
result = pc.ToDateTime (year, month, day, 12, 0, 0, 0);
year = result.Year;
month = result.Month;
day = result.Day;
} catch {
return false;
}
} else {
string d = GetDate (month, day, year, frm);

if (!DateTime.TryParseExact (d, Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out result) ||
!isValidDate)
return false;
}

if (!DateTime.TryParseExact (d, Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result) ||
!isValidDate)
return false;
Date = result;
return true;
}
Expand Down Expand Up @@ -377,6 +410,28 @@ public virtual void OnDateChanged (DateTimeEventArgs<DateTime> args)
{
DateChanged?.Invoke (args);
}

string ToJalaaliString (string format, DateTime date)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should have a unit test for this.

{
if (string.IsNullOrEmpty (format)) format = " yyyy/MM/dd";
PersianCalendar pc = new PersianCalendar ();


var year = pc.GetYear (date);
var month = pc.GetMonth (date);
var day = pc.GetDayOfMonth (date);


format = format.Replace ("yyyy", year.ToString (CultureInfo.InvariantCulture));
format = format.Replace ("yy", (year % 100).ToString ("00", CultureInfo.InvariantCulture));
format = format.Replace ("MM", month.ToString ("00", CultureInfo.InvariantCulture));
format = format.Replace ("M", month.ToString (CultureInfo.InvariantCulture));
format = format.Replace ("dd", day.ToString ("00", CultureInfo.InvariantCulture));
format = format.Replace ("d", day.ToString (CultureInfo.InvariantCulture));

return format;
}

}

/// <summary>
Expand All @@ -386,7 +441,7 @@ public class DateTimeEventArgs<T> : EventArgs {
/// <summary>
/// The old <see cref="DateField"/> or <see cref="TimeField"/> value.
/// </summary>
public T OldValue {get;}
public T OldValue { get; }

/// <summary>
/// The new <see cref="DateField"/> or <see cref="TimeField"/> value.
Expand Down
4 changes: 3 additions & 1 deletion UICatalog/Scenarios/Text.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public override void Setup ()
Y = Pos.Bottom (hexView) + 1,
Width = 20,
//ColorScheme = Colors.Dialog,
IsShortFormat = false
IsShortFormat = false,

};
Win.Add (dateField);

Expand All @@ -81,6 +82,7 @@ public override void Setup ()
dateField.TextChanged += (prev) => {
labelMirroringDateField.Text = dateField.Text;
};


_timeField = new TimeField (DateTime.Now.TimeOfDay) {
X = Pos.Right (labelMirroringDateField) + 5,
Expand Down