Click here to Skip to main content
15,178,008 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am from Serbia, and in our country each citizen has its own unique "number" given by birth called JMBG. It holds exactly 13 digits. It looks like '0704982763816' where first 7 digits represent date of birth (dd,mm,yyy). How to convert this to datetime type so that i am able to query the table for records with date of birth larger or less from that date?

What I have tried:

string unos = "0704982";
            DateTime datum= DateTime.ParseExact(unos, "ddmmyyy", System.Globalization.CultureInfo.InvariantCulture);
            MessageBox.Show(datum.ToString());

This returns 7.4.0982, but i need 7.4.1982. Also problem is for people born after 1999. year, for example 0704001 - returns 7.4.0001
Posted
Updated 7-Feb-20 2:37am

First of all, [mm] is reserved for minutes, not for months. Use [MM] instead!

Check this:
C#
string[] unosarray = new string[]{"0704982", "0704001"};
foreach(string unos in unosarray)
{
	string y = unos.Substring(4,1)=="9" ? "19" :  "20";
	string sdate = $"{unos.Substring(0,4)}{y}{unos.Substring(5,2)}";
	DateTime datum= DateTime.ParseExact(sdate, "ddMMyyyy", System.Globalization.CultureInfo.InvariantCulture);
	Console.WriteLine(datum.ToString("yyyy-MM-dd"));
}


result:
1982-04-07
2001-04-07
   
Comments
Gruja82 7-Feb-20 2:52am
   
I know [mm] is for minutes i made mistake.
TheRealSteveJudge 7-Feb-20 3:27am
   
Effective approach without too much code! 5*
Maciej Los 7-Feb-20 3:38am
   
Thank you.
In addition to Maciejs good answer here is another one.
This will work for dates from 1900 to 2899...

C#
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace JBMG
{
    class Program
    {
        private const string PatternJmbg = "(?<DAY>[\\d]{2})(?<MONTH>[\\d]{2})(?<YEAR>[\\d]{3})\\d{6}";

        static void Main()
        {
            var jmbgList = new List<string>
            {
                "0101006500006",
                "1311970000000"
            };

            foreach (var jmbg in jmbgList)
            {
                var match = Regex.Match(jmbg, PatternJmbg);

                if (match.Success)
                {
                    var dayString = match.Groups["DAY"].Value;
                    var monthString = match.Groups["MONTH"].Value;
                    var yearString = GetCompleteYear(match.Groups["YEAR"].Value);

                    var day = int.Parse(dayString);
                    var month = int.Parse(monthString);
                    var year = int.Parse(yearString);

                    var dateTime = GetDateTime(day, month, year);

                    // Now you have a DateTime object...
                }
            }

            Console.ReadKey();
        }

        private static DateTime GetDateTime(int day, int month, int year)
        {
            return new DateTime(year, month, day);
        }

        private static string GetCompleteYear(string partialYear)
        {
            if(string.IsNullOrWhiteSpace(partialYear)) throw new Exception("Input string must not be empty.");
            if(partialYear.Length != 3) throw new Exception("The length of the input string must be 3.");

            return partialYear[0] == '9' ? $"1{partialYear}" : $"2{partialYear}";
        }
    }
}
   
Comments
Maciej Los 7-Feb-20 3:40am
   
Regex is good alternative!
TheRealSteveJudge 7-Feb-20 3:46am
   
Thank you!
Richard Deeming 7-Feb-20 6:07am
   
I'd be inclined to make GetCompleteYear work with the parsed int rather than the string. That way, you avoid the extra string concatenation.
private static int GetCompleteYear(int partialYear)
{
    if (partialYear > 999) throw new ArgumentOutOfRangeException();
    return partialYear + (partialYear >= 900 ? 1000 : 2000);
}
...
var yearString = match.Groups["YEAR"].Value;
int year = GetCompleteYear(int.Parse(yearString));


You could also make the regex a little more specific:
private const string PatternJmbg = @"^(?<DAY>([012]\d)|(3[01]))(?<MONTH>(0\d)|(1[012]))(?<YEAR>[\d]{3})\d{6}$";
TheRealSteveJudge 7-Feb-20 8:11am
   
Good hints! Especially concerning the regex pattern. I was aware that my regex was not strict enough.
I have found this:
if (unos.Substring(4,1)=="9")
            {
               unos= unos.Insert(4, "1");

            }
            else if (unos.Substring(4,1)=="0")
            {
              unos=  unos.Insert(4, "2");
            }

Is there any other way?
   
Comments
Maciej Los 7-Feb-20 2:34am
   
Yes, there is! Please, see my answer.
Quote:
How to extract date from string?

As you can see converting date string with missing information do not regenerate that missing information, it is because the date format is not standard.
You need to standardize the string to a standard date format, you need to reinsert the missing thousand of the year, and for this, you need to use your knowledge that it is a birthday of human.
To standardize the string, you need to extract the century and deduce what is the missing thousand digit.
Quote:
Is there any other way?

No, there is no other way.
Details may differ, on how you want to use language features, but it is the idea.
   
Thank you all for you solutions. I used solution posted by
Maciej Los
in combination with my solution, but i decided to create sql function and use it in computed column which hold date of birth extracted from JMBG.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900