<commit_before>﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace CalbucciLib.ExtensionsGalore
{
	public enum DateTimeSignificance
	{
		ToSeconds,
		ToMinutes,
		ToHours,
		ToDays,
		ToMonths,
		ToYears
	};

	static public class DateTimeExtensions
	{
		private static readonly string[] _AMDesignators =
		{
			"a", "am", "a.m.", "a.m", "ص", "上午", "dop.", "dop", "πμ", "de.",
			"de", "午前", "오전", "pd", "el", "ق.ظ", "sa", "पूर्वाह्न", "r.n.", "rn", "পুর্বাহ্ন", "ਸਵੇਰ", "પૂર્વ મધ્યાહ્ન", "காலை",
			"పూర్వాహ్న", "ಪೂರ್ವಾಹ್ನ", "ৰাতিপু", "म.पू.", "སྔ་དྲོ", "ព្រឹក", "ເຊົ້າ", "ܩ.ܛ", "පෙ.ව.", "ጡዋት", "विहानी", "غ.م", "މކ",
			"safe", "owuro", "ututu", "ꂵꆪꈌꈐ", "چۈشتىن بۇرۇن", "saa moya z.m.", "m"
		};

		private static readonly string[] _PMDesignators =
		{
			"p", "pm", "p.m.", "p.m", "م", "下午", "odp.", "odp", "μμ", "du.",
			"du", "午後", "오후", "md", "pl", "ب.ظ", "ch", "अपराह्न", "i.n.", "in", "অপরাহ্ন", "ਸ਼ਾਮ", "ઉત્તર મધ્યાહ્ન", "மாலை",
			"అపరాహ్న", "ಅಪರಾಹ್ನ", "আবেলি", "म.नं.", "ཕྱི་དྲོ", "ល្ងាច", "ແລງ", "ܒ.ܛ", "ප.ව.", "ከሰዓት", "बेलुकी", "غ.و", "މފ",
			"yamma", "ale", "efifie", "ꂵꆪꈌꉈ", "چۈشتىن كېيىن", "saa moya z.n.", "f"
		};

		static private DateTime _UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
		static private DateTime _UnixEpochLocal = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
		static private DateTime _UnixEpochUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

		private static Calendar _DefaultCalendar;

		static DateTimeExtensions()
		{
			DateTimeFormatInfo dtfi = DateTimeFormatInfo.CurrentInfo;
			_DefaultCalendar = dtfi.Calendar;
		}

		// ==========================================================================
		//
		//    Parse
		//
		// ==========================================================================
		static public DateTime? ParseTime(string time)
		{
			if (string.IsNullOrWhiteSpace(time))
				return null;

			string ts = time.Trim();
			if (ts.Length == 0)
				return null;

			int minutes = 0;
			int seconds = 0;

			string[] parts = time.Split(':');
			if (parts.Length > 3)
				return null;

			string hourPart = parts[0];
			int pos = hourPart.IndexOf(c => char.IsDigit(c) || c == '-');
			if (pos == -1)
				return null;

			int hour = hourPart.Substring(pos).ToInt();
			if (hour < 0 || hour > 23)
				return null;

			bool isPM = _PMDesignators.Any(d => time.IndexOf(d, StringComparison.InvariantCultureIgnoreCase) >= 0);

			if (isPM)
			{
				if (hour < 12)
					hour += 12;
			}

			if (parts.Length >= 2)
			{
				string minutesPart = parts[1];
				pos = minutesPart.IndexOf(c => char.IsDigit(c) || c == '-');
				if (pos == -1)
					return null;
				minutes = minutesPart.Substring(pos).ToInt();
				if (minutes < 0 || minutes > 59)
					return null;

				if (parts.Length >= 3)
				{
					string secondsParts = parts[2];
					pos = secondsParts.IndexOf(c => char.IsDigit(c) || c == '-');
					if (pos == -1)
						return null;
					seconds = secondsParts.Substring(pos).ToInt();
					if (seconds < 0 || seconds > 59)
						return null;
				}
			}

			return new DateTime(1, 1, 1, hour, minutes, seconds);

		}

		// ==========================================================================
		//
		//    Conversion
		//
		// ==========================================================================
		static public DateTime FromUnixTime(long unixTime, DateTimeKind kind = DateTimeKind.Unspecified)
		{
			if (kind == DateTimeKind.Local)
				return _UnixEpochLocal.AddSeconds(unixTime);
			if (kind == DateTimeKind.Utc)
				return _UnixEpochUtc.AddSeconds(unixTime);
			return _UnixEpoch.AddSeconds(unixTime);
		}

		static public long ToUnixTime(this DateTime dateTime)
		{
			return (long)((dateTime - _UnixEpoch).TotalSeconds);
		}

		static public string ToRelativeTime(this DateTime utcDateTime, DateTime? baseDate = null)
		{
			if (baseDate == null)
				baseDate = DateTime.UtcNow;

			var ts = baseDate.Value - utcDateTime;
			var delta = Math.Round(ts.TotalSeconds, 0);

			if (delta < -0.1)
			{
				// In the future
				delta = -delta;
				ts = -ts;

				if (delta < 60)
				{
					return ts.Seconds == 1 ? "in one second" : "in " + ts.Seconds + " seconds";
				}
				if (delta < 120)
				{
					return "in one minute";
				}
				if (delta < 3000) // 50 * 60
				{
					return "in " + ts.Minutes + " minutes";
				}
				if (delta < 5400) // 90 * 60
				{
					return "in one hour ago";
				}
				if (delta < 86400) // 24 * 60 * 60
				{
					return "in " + ts.Hours + " hours";
				}
				if (delta < 172800) // 48 * 60 * 60
				{
					return "in one day";
				}<commit_msg>Fixed 'in one hour'<commit_after>﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace CalbucciLib.ExtensionsGalore
{
	public enum DateTimeSignificance
	{
		ToSeconds,
		ToMinutes,
		ToHours,
		ToDays,
		ToMonths,
		ToYears
	};

	static public class DateTimeExtensions
	{
		private static readonly string[] _AMDesignators =
		{
			"a", "am", "a.m.", "a.m", "ص", "上午", "dop.", "dop", "πμ", "de.",
			"de", "午前", "오전", "pd", "el", "ق.ظ", "sa", "पूर्वाह्न", "r.n.", "rn", "পুর্বাহ্ন", "ਸਵੇਰ", "પૂર્વ મધ્યાહ્ન", "காலை",
			"పూర్వాహ్న", "ಪೂರ್ವಾಹ್ನ", "ৰাতিপু", "म.पू.", "སྔ་དྲོ", "ព្រឹក", "ເຊົ້າ", "ܩ.ܛ", "පෙ.ව.", "ጡዋት", "विहानी", "غ.م", "މކ",
			"safe", "owuro", "ututu", "ꂵꆪꈌꈐ", "چۈشتىن بۇرۇن", "saa moya z.m.", "m"
		};

		private static readonly string[] _PMDesignators =
		{
			"p", "pm", "p.m.", "p.m", "م", "下午", "odp.", "odp", "μμ", "du.",
			"du", "午後", "오후", "md", "pl", "ب.ظ", "ch", "अपराह्न", "i.n.", "in", "অপরাহ্ন", "ਸ਼ਾਮ", "ઉત્તર મધ્યાહ્ન", "மாலை",
			"అపరాహ్న", "ಅಪರಾಹ್ನ", "আবেলি", "म.नं.", "ཕྱི་དྲོ", "ល្ងាច", "ແລງ", "ܒ.ܛ", "ප.ව.", "ከሰዓት", "बेलुकी", "غ.و", "މފ",
			"yamma", "ale", "efifie", "ꂵꆪꈌꉈ", "چۈشتىن كېيىن", "saa moya z.n.", "f"
		};

		static private DateTime _UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
		static private DateTime _UnixEpochLocal = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
		static private DateTime _UnixEpochUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

		private static Calendar _DefaultCalendar;

		static DateTimeExtensions()
		{
			DateTimeFormatInfo dtfi = DateTimeFormatInfo.CurrentInfo;
			_DefaultCalendar = dtfi.Calendar;
		}

		// ==========================================================================
		//
		//    Parse
		//
		// ==========================================================================
		static public DateTime? ParseTime(string time)
		{
			if (string.IsNullOrWhiteSpace(time))
				return null;

			string ts = time.Trim();
			if (ts.Length == 0)
				return null;

			int minutes = 0;
			int seconds = 0;

			string[] parts = time.Split(':');
			if (parts.Length > 3)
				return null;

			string hourPart = parts[0];
			int pos = hourPart.IndexOf(c => char.IsDigit(c) || c == '-');
			if (pos == -1)
				return null;

			int hour = hourPart.Substring(pos).ToInt();
			if (hour < 0 || hour > 23)
				return null;

			bool isPM = _PMDesignators.Any(d => time.IndexOf(d, StringComparison.InvariantCultureIgnoreCase) >= 0);

			if (isPM)
			{
				if (hour < 12)
					hour += 12;
			}

			if (parts.Length >= 2)
			{
				string minutesPart = parts[1];
				pos = minutesPart.IndexOf(c => char.IsDigit(c) || c == '-');
				if (pos == -1)
					return null;
				minutes = minutesPart.Substring(pos).ToInt();
				if (minutes < 0 || minutes > 59)
					return null;

				if (parts.Length >= 3)
				{
					string secondsParts = parts[2];
					pos = secondsParts.IndexOf(c => char.IsDigit(c) || c == '-');
					if (pos == -1)
						return null;
					seconds = secondsParts.Substring(pos).ToInt();
					if (seconds < 0 || seconds > 59)
						return null;
				}
			}

			return new DateTime(1, 1, 1, hour, minutes, seconds);

		}

		// ==========================================================================
		//
		//    Conversion
		//
		// ==========================================================================
		static public DateTime FromUnixTime(long unixTime, DateTimeKind kind = DateTimeKind.Unspecified)
		{
			if (kind == DateTimeKind.Local)
				return _UnixEpochLocal.AddSeconds(unixTime);
			if (kind == DateTimeKind.Utc)
				return _UnixEpochUtc.AddSeconds(unixTime);
			return _UnixEpoch.AddSeconds(unixTime);
		}

		static public long ToUnixTime(this DateTime dateTime)
		{
			return (long)((dateTime - _UnixEpoch).TotalSeconds);
		}

		static public string ToRelativeTime(this DateTime utcDateTime, DateTime? baseDate = null)
		{
			if (baseDate == null)
				baseDate = DateTime.UtcNow;

			var ts = baseDate.Value - utcDateTime;
			var delta = Math.Round(ts.TotalSeconds, 0);

			if (delta < -0.1)
			{
				// In the future
				delta = -delta;
				ts = -ts;

				if (delta < 60)
				{
					return ts.Seconds == 1 ? "in one second" : "in " + ts.Seconds + " seconds";
				}
				if (delta < 120)
				{
					return "in one minute";
				}
				if (delta < 3000) // 50 * 60
				{
					return "in " + ts.Minutes + " minutes";
				}
				if (delta < 5400) // 90 * 60
				{
					return "in one hour";
				}
				if (delta < 86400) // 24 * 60 * 60
				{
					return "in " + ts.Hours + " hours";
				}
				if (delta < 172800) // 48 * 60 * 60
				{
					return "in one day";
				}
{'fraction_non_alphanumeric': 0.24031007751937986, 'fraction_numerical': 0.021789231091556675, 'mean_word_length': 3.074690567648314, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2491704', 'n_tokens_mistral': 4707, 'n_tokens_neox': 3953, 'n_words': 858}