In VBA, How to convert a UTC UNIX timestamp to Local timezone Date in a simple way?

ぐ巨炮叔叔 提交于 2019-12-03 20:28:31
Matt Johnson-Pint

Probably the easiest way is via COM Interop to use the DateTime APIs built in to .NET. There's a good intro to this approach in this answer.

Create a C# class library. To make things simpler, target .NET Framework 4.6 or higher, so you can use the FromUnixTimeSeconds and ToUnixTimeSeconds methods on the DateTimeOffset class.

using System;
using System.Runtime.InteropServices;

namespace MyDateTimeLibrary
{
    [Serializable]
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class DateTimeFunctions
    {
        public DateTime UnixTimeToDateTime(int unixTimeInSeconds)
        {
            return DateTimeOffset.FromUnixTimeSeconds(unixTimeInSeconds).UtcDateTime;
        }

        public long DateTimeUtcToUnixTime(DateTime utcDateTime)
        {
            return new DateTimeOffset(utcDateTime, TimeSpan.Zero).ToUnixTimeSeconds();
        }

        public DateTime UtcToLocal(DateTime utcDateTime)
        {
            return utcDateTime.ToLocalTime();
        }

        public DateTime LocalToUtc(DateTime localDateTime)
        {
            return localDateTime.ToUniversalTime();
        }

        public DateTime TZSpecificDateTimeToUTC(DateTime sourceDateTime, string sourceTimeZoneId)
        {
            var tzi = TimeZoneInfo.FindSystemTimeZoneById(sourceTimeZoneId);
            return TimeZoneInfo.ConvertTimeToUtc(sourceDateTime, tzi);
        }

        public DateTime UTCToTZSpecificDateTime(DateTime utcDateTime, string destinationTimeZoneId)
        {
            var tzi = TimeZoneInfo.FindSystemTimeZoneById(destinationTimeZoneId);
            return TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, tzi);
        }
    }
}

For what you asked, you really only need the UnixTimeToDateTime and UtcToLocal methods from the above code, but I thought I'd throw a few more in for others that may be in similar situations. Really, anything you can do in .NET you can do here. The .NET DateTime, DateTimeOffset and TimeZoneInfo APIs are much easier and more reliable than the Win32 APIs you would need to do similar work.

Check the Register for COM interop option before you build (as mentioned in the answer linked earlier), or otherwise register your DLL with COM via the RegAsm.exe utility if you are deploying to another machine.

Next, add a reference from your VBA project to your newly registered MyDateTimeLibrary. Then use it, like so (for example):

Sub Test()

    Dim dtf As New MyDateTimeLibrary.DateTimeFunctions
    Dim utcDt As Date, localDt As Date

    utcDt = dtf.UnixTimeToDateTime(1487010504)
    localDt = dtf.UtcToLocal(utcDt)

    MsgBox ("UTC: " + CStr(utcDt) + vbCrLf + "Local: " + CStr(localDt))

    Set dtf = Nothing

End Sub

I'm sure you can refactor this to write some useful VBA functions that pass in and out the dates to convert, call those from Excel cells, or whatever your context is. I'll leave that part up to you.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!