Test code refactoring. Minor CI change.
This commit is contained in:
@@ -11,10 +11,10 @@ jobs:
|
|||||||
image: ghcr.io/catthehacker/ubuntu:act-latest
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
options: >-
|
options: >-
|
||||||
--privileged
|
--privileged
|
||||||
|
--add-host=host.testcontainers.internal:host-gateway
|
||||||
env:
|
env:
|
||||||
TESTCONTAINERS_RYUK_DISABLED: 'true'
|
# Testcontainers will substitute this host into GetConnectionString()
|
||||||
TESTCONTAINERS_CHECKS_DISABLE: 'true'
|
TESTCONTAINERS_HOST_OVERRIDE: host.testcontainers.internal
|
||||||
TESTCONTAINERS_HOST_OVERRIDE: host.docker.internal
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v4
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ public static class MariaDbClone
|
|||||||
await ExecAsync(root, $"USE `{databaseName}`; {createTable};");
|
await ExecAsync(root, $"USE `{databaseName}`; {createTable};");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//await Parallel.ForEachAsync(tables, async (table, cancellationToken) =>
|
||||||
|
//{
|
||||||
|
// var createTable = await ShowCreateTableAsync(root, templateDbName, table);
|
||||||
|
// // Run DDL in the new DB (the CREATE statement itself doesn't include db name)
|
||||||
|
// await ExecAsync(root, $"USE `{databaseName}`; {createTable};");
|
||||||
|
//});
|
||||||
|
|
||||||
// 2) Copy data
|
// 2) Copy data
|
||||||
foreach (var table in tables)
|
foreach (var table in tables)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using DotNet.Testcontainers.Builders;
|
using DotNet.Testcontainers.Builders;
|
||||||
using JSMR.Tests.Fixtures;
|
using JSMR.Tests.Fixtures;
|
||||||
using JSMR.Tests.Ingestion;
|
|
||||||
using Testcontainers.MariaDb;
|
using Testcontainers.MariaDb;
|
||||||
|
|
||||||
[assembly: AssemblyFixture(typeof(MariaDbContainerFixture))]
|
[assembly: AssemblyFixture(typeof(MariaDbContainerFixture))]
|
||||||
|
|||||||
9
JSMR.Tests/Ingestion/English/EnglishIngestionTestBase.cs
Normal file
9
JSMR.Tests/Ingestion/English/EnglishIngestionTestBase.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using JSMR.Infrastructure.Common.Languages;
|
||||||
|
using JSMR.Tests.Fixtures;
|
||||||
|
|
||||||
|
namespace JSMR.Tests.Ingestion.English;
|
||||||
|
|
||||||
|
public abstract class EnglishIngestionTestBase(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
||||||
|
{
|
||||||
|
protected static LanguageIdentifier LanguageIdentifier = new();
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using JSMR.Application.Scanning.Contracts;
|
using JSMR.Application.Scanning.Contracts;
|
||||||
using JSMR.Application.Scanning.Ports;
|
using JSMR.Application.Scanning.Ports;
|
||||||
using JSMR.Infrastructure.Common.Languages;
|
|
||||||
using JSMR.Infrastructure.Data;
|
using JSMR.Infrastructure.Data;
|
||||||
using JSMR.Infrastructure.Ingestion;
|
using JSMR.Infrastructure.Ingestion;
|
||||||
using JSMR.Tests.Fixtures;
|
using JSMR.Tests.Fixtures;
|
||||||
@@ -9,16 +8,12 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.English;
|
namespace JSMR.Tests.Ingestion.English;
|
||||||
|
|
||||||
public class English_Fail_Attempted_Insert_When_Not_English_Tests(MariaDbContainerFixture container)
|
public class English_Fail_Attempted_Insert_When_Not_English_Tests(MariaDbContainerFixture container) : EnglishIngestionTestBase(container)
|
||||||
{
|
{
|
||||||
private readonly LanguageIdentifier languageIdentifier = new();
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Fail_Attempted_Insert_When_Not_English()
|
public async Task Fail_Attempted_Insert_When_Not_English()
|
||||||
{
|
{
|
||||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
await using AppDbContext dbContext = await GetAppDbContextAsync();
|
||||||
container.RootConnectionString,
|
|
||||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
|
||||||
|
|
||||||
VoiceWorkIngest ingest = new()
|
VoiceWorkIngest ingest = new()
|
||||||
{
|
{
|
||||||
@@ -29,7 +24,7 @@ public class English_Fail_Attempted_Insert_When_Not_English_Tests(MariaDbContain
|
|||||||
Description = "最高の製品です!"
|
Description = "最高の製品です!"
|
||||||
};
|
};
|
||||||
|
|
||||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
EnglishVoiceWorkUpdater updater = new(dbContext, LanguageIdentifier);
|
||||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||||
|
|
||||||
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using JSMR.Application.Scanning.Contracts;
|
using JSMR.Application.Scanning.Contracts;
|
||||||
using JSMR.Application.Scanning.Ports;
|
using JSMR.Application.Scanning.Ports;
|
||||||
using JSMR.Infrastructure.Common.Languages;
|
|
||||||
using JSMR.Infrastructure.Data;
|
using JSMR.Infrastructure.Data;
|
||||||
using JSMR.Infrastructure.Ingestion;
|
using JSMR.Infrastructure.Ingestion;
|
||||||
using JSMR.Tests.Fixtures;
|
using JSMR.Tests.Fixtures;
|
||||||
@@ -9,16 +8,12 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.English;
|
namespace JSMR.Tests.Ingestion.English;
|
||||||
|
|
||||||
public class English_Fail_Attempted_Insert_With_Missing_Circle_Tests(MariaDbContainerFixture container) //: IAssemblyFixture<MariaDbContainerFixture>
|
public class English_Fail_Attempted_Insert_With_Missing_Circle_Tests(MariaDbContainerFixture container) : EnglishIngestionTestBase(container)
|
||||||
{
|
{
|
||||||
private readonly LanguageIdentifier languageIdentifier = new();
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Fail_Attempted_Insert_With_Missing_Circle()
|
public async Task Fail_Attempted_Insert_With_Missing_Circle()
|
||||||
{
|
{
|
||||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
await using AppDbContext dbContext = await GetAppDbContextAsync();
|
||||||
container.RootConnectionString,
|
|
||||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
|
||||||
|
|
||||||
VoiceWorkIngest ingest = new()
|
VoiceWorkIngest ingest = new()
|
||||||
{
|
{
|
||||||
@@ -29,7 +24,7 @@ public class English_Fail_Attempted_Insert_With_Missing_Circle_Tests(MariaDbCont
|
|||||||
Description = "EN Desc"
|
Description = "EN Desc"
|
||||||
};
|
};
|
||||||
|
|
||||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
EnglishVoiceWorkUpdater updater = new(dbContext, LanguageIdentifier);
|
||||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||||
|
|
||||||
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using JSMR.Application.Scanning.Contracts;
|
using JSMR.Application.Scanning.Contracts;
|
||||||
using JSMR.Application.Scanning.Ports;
|
using JSMR.Application.Scanning.Ports;
|
||||||
using JSMR.Infrastructure.Common.Languages;
|
|
||||||
using JSMR.Infrastructure.Data;
|
using JSMR.Infrastructure.Data;
|
||||||
using JSMR.Infrastructure.Ingestion;
|
using JSMR.Infrastructure.Ingestion;
|
||||||
using JSMR.Tests.Fixtures;
|
using JSMR.Tests.Fixtures;
|
||||||
@@ -9,16 +8,12 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.English;
|
namespace JSMR.Tests.Ingestion.English;
|
||||||
|
|
||||||
public class English_Fail_Attempted_Insert_With_Missing_Product_Tests(MariaDbContainerFixture container)
|
public class English_Fail_Attempted_Insert_With_Missing_Product_Tests(MariaDbContainerFixture container) : EnglishIngestionTestBase(container)
|
||||||
{
|
{
|
||||||
private readonly LanguageIdentifier languageIdentifier = new();
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Fail_Attempted_Insert_With_Missing_Product()
|
public async Task Fail_Attempted_Insert_With_Missing_Product()
|
||||||
{
|
{
|
||||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
await using AppDbContext dbContext = await GetAppDbContextAsync();
|
||||||
container.RootConnectionString,
|
|
||||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
|
||||||
|
|
||||||
VoiceWorkIngest ingest = new()
|
VoiceWorkIngest ingest = new()
|
||||||
{
|
{
|
||||||
@@ -29,7 +24,7 @@ public class English_Fail_Attempted_Insert_With_Missing_Product_Tests(MariaDbCon
|
|||||||
Description = "EN Desc"
|
Description = "EN Desc"
|
||||||
};
|
};
|
||||||
|
|
||||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
EnglishVoiceWorkUpdater updater = new(dbContext, LanguageIdentifier);
|
||||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||||
|
|
||||||
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using JSMR.Application.Scanning.Contracts;
|
using JSMR.Application.Scanning.Contracts;
|
||||||
using JSMR.Application.Scanning.Ports;
|
using JSMR.Application.Scanning.Ports;
|
||||||
using JSMR.Domain.Entities;
|
using JSMR.Domain.Entities;
|
||||||
using JSMR.Infrastructure.Common.Languages;
|
|
||||||
using JSMR.Infrastructure.Data;
|
using JSMR.Infrastructure.Data;
|
||||||
using JSMR.Infrastructure.Ingestion;
|
using JSMR.Infrastructure.Ingestion;
|
||||||
using JSMR.Tests.Fixtures;
|
using JSMR.Tests.Fixtures;
|
||||||
@@ -10,16 +9,12 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.English;
|
namespace JSMR.Tests.Ingestion.English;
|
||||||
|
|
||||||
public class English_Insert_Then_Update_Tests(MariaDbContainerFixture container) //: IAssemblyFixture<MariaDbContainerFixture>
|
public class English_Insert_Then_Update_Tests(MariaDbContainerFixture container) : EnglishIngestionTestBase(container)
|
||||||
{
|
{
|
||||||
private readonly LanguageIdentifier languageIdentifier = new();
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Insert_Then_Update()
|
public async Task Insert_Then_Update()
|
||||||
{
|
{
|
||||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
await using AppDbContext dbContext = await GetAppDbContextAsync();
|
||||||
container.RootConnectionString,
|
|
||||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
|
||||||
|
|
||||||
// Part 1 -- Insert
|
// Part 1 -- Insert
|
||||||
VoiceWorkIngest ingest = new()
|
VoiceWorkIngest ingest = new()
|
||||||
@@ -31,7 +26,7 @@ public class English_Insert_Then_Update_Tests(MariaDbContainerFixture container)
|
|||||||
Description = "An average product. (EN)"
|
Description = "An average product. (EN)"
|
||||||
};
|
};
|
||||||
|
|
||||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
EnglishVoiceWorkUpdater updater = new(dbContext, LanguageIdentifier);
|
||||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], TestContext.Current.CancellationToken);
|
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], TestContext.Current.CancellationToken);
|
||||||
|
|
||||||
VoiceWork voiceWork = await dbContext.VoiceWorks.SingleAsync(v => v.ProductId == "RJ0000001", TestContext.Current.CancellationToken);
|
VoiceWork voiceWork = await dbContext.VoiceWorks.SingleAsync(v => v.ProductId == "RJ0000001", TestContext.Current.CancellationToken);
|
||||||
|
|||||||
15
JSMR.Tests/Ingestion/IngestionTestsBase.cs
Normal file
15
JSMR.Tests/Ingestion/IngestionTestsBase.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using JSMR.Infrastructure.Data;
|
||||||
|
using JSMR.Tests.Fixtures;
|
||||||
|
|
||||||
|
namespace JSMR.Tests.Ingestion;
|
||||||
|
|
||||||
|
public abstract class IngestionTestsBase(MariaDbContainerFixture container)
|
||||||
|
{
|
||||||
|
protected async Task<AppDbContext> GetAppDbContextAsync()
|
||||||
|
{
|
||||||
|
return await MariaDbClone.CloneFromTemplateAsync(
|
||||||
|
container.RootConnectionString,
|
||||||
|
container.TemplateDbName,
|
||||||
|
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Fail_Attempted_Insert_With_Spam_Circle_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Fail_Attempted_Insert_With_Spam_Circle_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Fail_Attempted_Insert_With_Spam_Circle()
|
public async Task Fail_Attempted_Insert_With_Spam_Circle()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Fail_Attempted_Update_With_Decreased_Downloads_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Fail_Attempted_Update_With_Decreased_Downloads_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Fail_Attempted_Update_With_Decreased_Downloads()
|
public async Task Fail_Attempted_Update_With_Decreased_Downloads()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Fail_Attempted_Update_With_Sales_Date_Reversal_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Fail_Attempted_Update_With_Sales_Date_Reversal_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Fail_Attempted_Update_With_Decreased_Downloads()
|
public async Task Fail_Attempted_Update_With_Decreased_Downloads()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Insert_New_Release_And_Scan_Again_Later_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Insert_New_Release_And_Scan_Again_Later_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Insert_New_Release_And_Scan_Again_Later()
|
public async Task Insert_New_Release_And_Scan_Again_Later()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Insert_New_Release_With_New_Tags_And_Creators_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Insert_New_Release_With_New_Tags_And_Creators_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Insert_New_Release_With_New_Tags_And_Creators()
|
public async Task Insert_New_Release_With_New_Tags_And_Creators()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Insert_New_Upcoming_And_Scan_Again_Later_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Insert_New_Upcoming_And_Scan_Again_Later_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Insert_New_Upcoming_And_Scan_Again_Later()
|
public async Task Insert_New_Upcoming_And_Scan_Again_Later()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Insert_New_Upcoming_Release_Same_Day_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Insert_New_Upcoming_Release_Same_Day_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Insert_New_Upcoming_Release_Same_Day()
|
public async Task Insert_New_Upcoming_Release_Same_Day()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Shouldly;
|
|||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public class Insert_New_Upcoming_With_Existing_Tags_And_Creators_Tests(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
public class Insert_New_Upcoming_With_Existing_Tags_And_Creators_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Insert_New_Upcoming_With_Existing_Tags_And_Creators()
|
public async Task Insert_New_Upcoming_With_Existing_Tags_And_Creators()
|
||||||
|
|||||||
@@ -4,22 +4,13 @@ using JSMR.Infrastructure.Common.Time;
|
|||||||
using JSMR.Infrastructure.Data;
|
using JSMR.Infrastructure.Data;
|
||||||
using JSMR.Infrastructure.Ingestion;
|
using JSMR.Infrastructure.Ingestion;
|
||||||
using JSMR.Tests.Fixtures;
|
using JSMR.Tests.Fixtures;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace JSMR.Tests.Ingestion.Japanese;
|
namespace JSMR.Tests.Ingestion.Japanese;
|
||||||
|
|
||||||
public abstract class IngestionTestsBase(MariaDbContainerFixture container)
|
public abstract class JapaneseIngestionTestsBase(MariaDbContainerFixture container) : IngestionTestsBase(container)
|
||||||
{
|
{
|
||||||
protected async Task<AppDbContext> GetAppDbContextAsync()
|
|
||||||
{
|
|
||||||
return await MariaDbClone.CloneFromTemplateAsync(
|
|
||||||
container.RootConnectionString,
|
|
||||||
container.TemplateDbName,
|
|
||||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static async Task<VoiceWorkUpsertResult[]> UpsertAsync(AppDbContext dbContext, DateTime dateTime, VoiceWorkIngest[] ingests)
|
protected static async Task<VoiceWorkUpsertResult[]> UpsertAsync(AppDbContext dbContext, DateTime dateTime, VoiceWorkIngest[] ingests)
|
||||||
{
|
{
|
||||||
DateTime utcDateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
|
DateTime utcDateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
|
||||||
Reference in New Issue
Block a user