extract part of string

StewartBW 745 Reputation points
2024-06-27T08:52:07.12+00:00

Hello experts,

I'm reading Vcf contact files, the only fields I have issues reading are 2 multi-line fields: NOTE and KEY

Because I don't know how many lines it lasts, the fields order can be different in each file so just need an idea how to parse these 2 multi-line fields?

By the way, how to parse this REV string to date and time?

20240623T081758Z

TryParseExact does not parse strings like "20221114T225355Z" or if it does not end of Z :(

Sample:

BEGIN:VCARD
VERSION:VERSION:2.1
N;LANGUAGE=en-us:;Georges
FN:Georges
NOTE;ENCODING=QUOTED-PRINTABLE:<html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; chars=
et=3Dutf-8"> <meta name=3D"Generator" content=3D"Microsoft Exchange Server"=
> <!-- converted from rtf --> <style><!-- =2EEmailQuote { margin-left: 1pt;=
 padding-left: 4pt; border-left: #800000 2px solid; } --></style> </head> <=
body> <font face=3D"Calibri" size=3D"2"><span style=3D"font-size:11pt;"> <d=
iv style=3D"margin-bottom:6pt;">Saturday, September 17, 2022 7:34 PM:<img s=
rc=3D"cid:6BB92315A7EAE10E516B9A051AB90B0C88469968@1"> </div> <div style=3D"=
margin-bottom:6pt;">Notes are here</div> <div><font face=3D"Arial" size=3D"=
2"><span style=3D"font-size:10pt;">&nbsp;</span></font></div> <div style=3D"=
margin-bottom:6pt;">Notes are here</div> <div style=3D"margin-bottom:6pt;">=
&nbsp;</div> </span></font> </body> </html>
ORG:comp co;dept
KEY;X509;ENCODING=BASE64:
 MIIF6DCCA9CgAwIBAgIQSn+Q+fs4+1BweWY3kIcBwDANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UE
 BhMCSVQgdfhjhgktyryiuyoiuohmhgcGGDFHGJKJUKKHJGJHGJHGJHGJGHBQaWV0cm8xFzAVBgNV
 bw8mToZYbb1dFGHHFGHGFHGFHGFHJGF9dfNtkzg==
REV:20240623T081758Z
END:VCARD

Thanks in advance.

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,642 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Michael Taylor 50,506 Reputation points
    2024-06-27T19:01:44.2533333+00:00

    DateTime.ParseExact works here, you just need to use the right custom flags.

    Dim input As String = "20240623T081758Z"
    
    Dim dt As DateTime = DateTime.ParseExact(value, "yyyyMMddTHHmmssZ", System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.AdjustToUniversal)
    

    A few notes here. Assuming your hours are in 24-hour format. Using current culture for typical defaults. Because you're getting the time in UTC with the Z, DateTime doesn't tend to like that. If you always know it is that then you can simply strip it off. But specifying AdjustToUniversal seems to handle this case as well. If you cannot do that then just strip off the Z before parsing.

    0 comments No comments

  2. Jiachen Li-MSFT 28,001 Reputation points Microsoft Vendor
    2024-06-28T01:50:45.3966667+00:00

    Hi @StewartBW ,

    You can use a state machine approach to properly detect and parse the fields, even if they span multiple lines.

            Dim inNote As Boolean = False
            Dim inKey As Boolean = False
    
            For Each line As String In lines
                If line.StartsWith("NOTE") Then
                    inKey = False
                    inNote = True
                    noteBuilder.Append(line.Substring(line.IndexOf(":"c) + 1).Trim())
                ElseIf line.StartsWith("KEY") Then
                    inNote = False
                    inKey = True
                    keyBuilder.Append(line.Substring(line.IndexOf(":"c) + 1).Trim())
                ElseIf line.StartsWith("END:VCARD") Then
                    inNote = False
                    inKey = False
                ElseIf line.StartsWith("BEGIN:VCARD") Then
                    inNote = False
                    inKey = False
                ElseIf line.StartsWith("VERSION:") Then
                    inNote = False
                    inKey = False
                ElseIf line.StartsWith("N;LANGUAGE") Then
                    inNote = False
                    inKey = False
                ElseIf line.StartsWith("FN:") Then
                    inNote = False
                    inKey = False
                ElseIf line.StartsWith("ORG:") Then
                    inNote = False
                    inKey = False
                ElseIf line.StartsWith("REV:") Then
                    inNote = False
                    inKey = False
                Else
                    If inNote Then
                        noteBuilder.Append(line.Trim())
                    End If
                    If inKey Then
                        keyBuilder.Append(line.Trim())
                    End If
                End If
            Next
    
    

    Uses DateTime.TryParseExact to parse the REV string using the exact format provided.

            Dim revString As String = "20240623T081758Z"
            Dim revDate As DateTime
    
            If DateTime.TryParseExact(revString, "yyyyMMdd'T'HHmmss'Z'", 
                                      CultureInfo.InvariantCulture, 
                                      DateTimeStyles.AssumeUniversal, 
                                      revDate) Then
                Console.WriteLine("Parsed Date: " & revDate.ToString("yyyy-MM-dd HH:mm:ss"))
            Else
                Console.WriteLine("Failed to parse date.")
            End If
    

    Best Regards.

    Jiachen Li


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments