% DateTimeUtils - A suite of utilities to provide functionalities
% associated with conversions between MATLAB datetime and java.util.Date

% Copyright 2016-2021 The MathWorks, Inc.
classdef DateTimeUtils < handle
    
    properties (Constant, Access = private)
        % These two properties define the string representation of MATLAB
        % datetime objects that matches the java.util.Date format.
        Format = 'eee MMM dd HH:mm:ss z yyyy';
        Locale = 'en_US';
    end
    
    methods (Access = public, Static)
        % Returns a java.util.Date-like string for a given MATLAB datetime.
        % If the given datetime is empty or NaT, returns the empty string
        % ''.
        function javaDateStr = getJavaDateStr(matlabDateTime)
            import parallel.internal.general.DateTimeUtils
            
            if isempty(matlabDateTime)
                javaDateStr = '';
            else
                validateattributes(matlabDateTime, {'datetime'}, {'scalar'});
                if isnat(matlabDateTime)
                    javaDateStr = '';
                else
                    javaDateStr = char(datetime(matlabDateTime, 'Format', DateTimeUtils.Format, 'TimeZone', 'local'), [], DateTimeUtils.Locale);
                end
            end
        end
        
        % Returns a MATLAB datetime for a given java.util.Date-like string.
        function matlabDateTime = fromJavaDateStr(javaDateStr)
            import parallel.internal.general.DateTimeUtils
            
            matlabDateTime = datetime(javaDateStr, 'InputFormat', DateTimeUtils.Format, 'TimeZone', 'local', 'Locale', DateTimeUtils.Locale);
        end
        
        % Converts a single MATLAB datetime to a java.util.Date.
        % If the given datetime is empty or NaT, this function returns [],
        % which maps to a Java null
        function javaDate = getJavaDate(matlabDateTime)
            if isempty(matlabDateTime)
                javaDate = []; % Maps to a Java null
            else
                validateattributes(matlabDateTime, {'datetime'}, {'scalar'});
                if isnat(matlabDateTime)
                    javaDate = []; % Maps to a Java null
                else
                    % The double value of msSinceEpoch will be truncated in the conversion to a Java long.
                    % This behaviour matches the millisecond display of a MATLAB datetime
                    msSinceEpoch = posixtime(matlabDateTime) * 1000; % Seconds to milliseconds
                    javaDate = java.util.Date(msSinceEpoch);
                end
            end
        end
        
        % Converts a single java.util.Date to a MATLAB datetime.
        % If the given java.util.Date is empty, returns datetime.empty().
        % Otherwise the returned datetime represents the exact time of the java.util.Date
        % in the MATLAB TimeZone 'local' to preserve region-specific display formatting.
        function matlabDateTime = getMatlabDateTime(javaDate)
            if isempty(javaDate)
                matlabDateTime = datetime.empty();
            else
                validateattributes(javaDate, {'java.util.Date'}, {'scalar'});
                matlabDateTime = datetime(javaDate.getTime() / 1000, ... % Milliseconds to seconds
                    'ConvertFrom', 'posixtime', 'TimeZone', 'local');
            end
        end
    end
    
end
