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 all 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
86 changes: 77 additions & 9 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 => isShort ? shortFieldLen : longFieldLen;
string format => isShort ? shortFormat : longFormat;
Expand All @@ -47,9 +48,14 @@ 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, isShort);

}

/// <summary>
Expand All @@ -61,19 +67,28 @@ 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 ("")
{
Width = fieldLen + 2;

this.isJalaali = isJalaali;
if (!isJalaali)
this.isShort = true;
Width = FieldLen + 2;

Initialize (date);
}

void Initialize (DateTime date, bool isShort = false)
{
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;

this.isShort = isShort;

Date = date;
CursorPosition = 1;
TextChanged += DateField_Changed;
Expand Down Expand Up @@ -109,8 +124,10 @@ void Initialize (DateTime date, bool isShort = false)
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 @@ -155,14 +172,23 @@ public DateTime Date {

var oldData = date;
date = value;
this.Text = value.ToString (format);
var args = new DateTimeEventArgs<DateTime> (oldData, value, 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 @@ -236,7 +262,27 @@ 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)
Expand Down Expand Up @@ -420,6 +466,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 Down
4 changes: 3 additions & 1 deletion UICatalog/Scenarios/Text.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ void TextView_DrawContent (Rect e)
Y = Pos.Bottom (hexView) + 1,
Width = 20,
//ColorScheme = Colors.Dialog,
IsShortFormat = false
IsShortFormat = false,

};
Win.Add (dateField);

Expand All @@ -110,6 +111,7 @@ void TextView_DrawContent (Rect e)
dateField.TextChanged += (prev) => {
labelMirroringDateField.Text = dateField.Text;
};


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