Skip to content
Merged
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
28 changes: 28 additions & 0 deletions PdfSharpCore.Test/Pdfs/PdfDateTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using FluentAssertions;
using PdfSharpCore.Pdf;
using Xunit;

namespace PdfSharpCore.Test.Pdfs
{
public class PdfDateTests
{
// format for pdf date is generally D:YYYYMMDDHHmmSSOHH'mm'

[Fact]
public void ParseDateString_WithTimezoneOffset()
{
var pdfDate = new PdfDate("D:19981223195200-02'00'");
var expectedDateWithOffset = new DateTimeOffset(new DateTime(1998, 12, 23, 19, 52, 0), new TimeSpan(-2, 0, 0));
pdfDate.Value.ToUniversalTime().Should().Be(expectedDateWithOffset.UtcDateTime);
}

[Fact]
public void ParseDateString_WithNoOffset()
{
var pdfDate = new PdfDate("D:19981223195200Z");
var expectedDateWithOffset = new DateTimeOffset(new DateTime(1998, 12, 23, 19, 52, 0), new TimeSpan(0, 0, 0));
pdfDate.Value.ToUniversalTime().Should().Be(expectedDateWithOffset.UtcDateTime);
}
}
}
29 changes: 19 additions & 10 deletions PdfSharpCore/Pdf.IO/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1372,35 +1372,44 @@ private PdfTrailer ReadXRefStream(PdfCrossReferenceTable xrefTable)
/// <summary>
/// Parses a PDF date string.
/// </summary>
/// <remarks>
/// Format is
/// YYYY Year MM month DD day (01-31) HH hour (00-23) mm minute (00-59) ss second (00.59)
/// O is the relationship of local time to Universal Time (UT), denoted by one of the characters +, -, or Z (see below)
/// HH followed by ' is the absolute value of the offset from UT in hours (00-23)
/// mm followed by ' is the absolute value of the offset from UT in minutes (00-59)
/// For example, December 23, 1998, at 7:52 PM, U.S.Pacific Standard Time, is represented by the string,
/// D:19981223195200-08'00'
/// </remarks>

internal static DateTime ParseDateTime(string date, DateTime errorValue) // TODO: TryParseDateTime
{
DateTime datetime = errorValue;
try
{
if (date.StartsWith("D:"))
{
// Format is
// D:YYYYMMDDHHmmSSOHH'mm'
// ^2 ^10 ^16 ^20
int length = date.Length;
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, hh = 0, mm = 0;
char o = 'Z';
if (length >= 10)
{
year = Int32.Parse(date.Substring(2, 4));
month = Int32.Parse(date.Substring(6, 2));
day = Int32.Parse(date.Substring(8, 2));
year = int.Parse(date.Substring(2, 4));
month = int.Parse(date.Substring(6, 2));
day = int.Parse(date.Substring(8, 2));
if (length >= 16)
{
hour = Int32.Parse(date.Substring(10, 2));
minute = Int32.Parse(date.Substring(12, 2));
second = Int32.Parse(date.Substring(14, 2));
hour = int.Parse(date.Substring(10, 2));
minute = int.Parse(date.Substring(12, 2));
second = int.Parse(date.Substring(14, 2));
if (length >= 23)
{
if ((o = date[16]) != 'Z')
{
hh = Int32.Parse(date.Substring(17, 2));
mm = Int32.Parse(date.Substring(20, 2));
hh = int.Parse(date.Substring(17, 2));
mm = int.Parse(date.Substring(20, 2));
}
}
}
Expand All @@ -1417,7 +1426,7 @@ internal static DateTime ParseDateTime(string date, DateTime errorValue) // TOD
datetime = datetime.Subtract(ts);
}
// Now that we converted datetime to UTC, mark it as UTC.
DateTime.SpecifyKind(datetime, DateTimeKind.Utc);
datetime = DateTime.SpecifyKind(datetime, DateTimeKind.Utc);
}
else
{
Expand Down
19 changes: 6 additions & 13 deletions PdfSharpCore/Pdf/PdfDate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ namespace PdfSharpCore.Pdf
[DebuggerDisplay("({Value})")]
public sealed class PdfDate : PdfItem
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfDate"/> class.
/// </summary>
public PdfDate()
{ }

/// <summary>
/// Initializes a new instance of the <see cref="PdfDate"/> class.
/// </summary>
Expand All @@ -64,20 +58,19 @@ public PdfDate(DateTime value)
/// <summary>
/// Gets the value as DateTime.
/// </summary>
public DateTime Value
{
public DateTime Value =>
// This class must behave like a value type. Therefore it cannot be changed (like System.String).
get { return _value; }
}
DateTime _value;
_value;

readonly DateTime _value;

/// <summary>
/// Returns the value in the PDF date format.
/// </summary>
public override string ToString()
{
string delta = _value.ToString("zzz").Replace(':', '\'');
return String.Format("D:{0:yyyyMMddHHmmss}{1}'", _value, delta);
var delta = _value.ToString("zzz").Replace(':', '\'');
return $"D:{_value:yyyyMMddHHmmss}{delta}'";
}

/// <summary>
Expand Down