code: def astype_nansafe(arr, dtype, copy=True, skipna=False):
      """
      Cast the elements of an array to a given dtype a nan-safe manner.
  
      Parameters
      ----------
      arr : ndarray
      dtype : np.dtype
      copy : bool, default True
          If False, a view will be attempted but may fail, if
          e.g. the item sizes don't align.
      skipna: bool, default False
          Whether or not we should skip NaN when casting as a string-type.
  
      Raises
      ------
      ValueError
          The dtype was a datetime64/timedelta64 dtype, but it had no unit.
      """
  
      # dispatch on extension dtype if needed
      if is_extension_array_dtype(dtype):
          return dtype.construct_array_type()._from_sequence(
              arr, dtype=dtype, copy=copy
          )
  
      if not isinstance(dtype, np.dtype):
          dtype = pandas_dtype(dtype)
  
      if issubclass(dtype.type, text_type):
          # in Py3 that's str, in Py2 that's unicode
          return lib.astype_unicode(arr.ravel(), skipna=skipna).reshape(
              arr.shape
          )
  
      elif issubclass(dtype.type, string_types):
          return lib.astype_str(arr.ravel(), skipna=skipna).reshape(
              arr.shape
          )
  
      elif is_datetime64_dtype(arr):
          if is_object_dtype(dtype):
              return tslib.ints_to_pydatetime(arr.view(np.int64))
          elif dtype == np.int64:
              return arr.view(dtype)
  
          # allow frequency conversions
          if dtype.kind == "M":
              return arr.astype(dtype)
  
          raise TypeError(
              "cannot astype a datetimelike from [{from_dtype}] "
              "to [{to_dtype}]".format(
                  from_dtype=arr.dtype, to_dtype=dtype
              )
          )
  
      elif is_timedelta64_dtype(arr):
          if is_object_dtype(dtype):
              return tslibs.ints_to_pytimedelta(arr.view(np.int64))
          elif dtype == np.int64:
              return arr.view(dtype)
  
          # in py3, timedelta64[ns] are int64
          if (PY3 and dtype not in [_INT64_DTYPE, _TD_DTYPE]) or (
              not PY3 and dtype != _TD_DTYPE
          ):
              # allow frequency conversions
              # we return a float here!
              if dtype.kind == "m":
                  mask = isna(arr)
                  result = arr.astype(dtype).astype(np.float64)
                  result[mask] = np.nan
                  return result
          elif dtype == _TD_DTYPE:
              return arr.astype(_TD_DTYPE, copy=copy)
  
          raise TypeError(
              "cannot astype a timedelta from [{from_dtype}] "
              "to [{to_dtype}]".format(
                  from_dtype=arr.dtype, to_dtype=dtype
              )
          )
  
      elif np.issubdtype(arr.dtype, np.floating) and np.issubdtype(
          dtype, np.integer
      ):
          if not np.isfinite(arr).all():
              raise ValueError(
                  "Cannot convert non-finite values (NA or inf) to "
                  "integer"
              )
  
      elif is_object_dtype(arr):
          # work around NumPy brokenness, #1987
          if np.issubdtype(dtype.type, np.integer):
              return lib.astype_intsafe(arr.ravel(), dtype).reshape(
                  arr.shape
              )
  
          # if we have a datetime/timedelta array of objects
          # then coerce to a proper dtype and recall astype_nansafe
  
          elif is_datetime64_dtype(dtype):
              from pandas import to_datetime
  
              return astype_nansafe(
                  to_datetime(arr).values, dtype, copy=copy
              )
          elif is_timedelta64_dtype(dtype):
              from pandas import to_timedelta
  
              return astype_nansafe(
                  to_timedelta(arr).values, dtype, copy=copy
              )
  
      if dtype.name in ("datetime64", "timedelta64"):
          msg = (
              "The '{dtype}' dtype has no unit. "
              "Please pass in '{dtype}[ns]' instead."
          )
          raise ValueError(msg.format(dtype=dtype.name))
  
      if copy or is_object_dtype(arr) or is_object_dtype(dtype):
          # Explicit copy, or required since NumPy can't view from / to object.
          return arr.astype(dtype, copy=True)
  
      return arr.view(dtype)
  
imports: from datetime import datetime, timedelta
  import numpy
  from pandas._libs import lib, tslib, tslibs
  from pandas._libs.tslibs import NaT, OutOfBoundsDatetime, Period, iNaT
  from pandas.compat import PY3, string_types, text_type, to_str
  from .common import _INT64_DTYPE, _NS_DTYPE, _POSSIBLY_CAST_DTYPES, _TD_DTYPE, ensure_int8, ensure_int16, ensure_int32, ensure_int64, ensure_object, is_bool, is_bool_dtype, is_categorical_dtype, is_complex, is_complex_dtype, is_datetime64_dtype, is_datetime64_ns_dtype, is_datetime64tz_dtype, is_datetime_or_timedelta_dtype, is_datetimelike, is_dtype_equal, is_extension_array_dtype, is_extension_type, is_float, is_float_dtype, is_integer, is_integer_dtype, is_object_dtype, is_scalar, is_string_dtype, is_timedelta64_dtype, is_timedelta64_ns_dtype, is_unsigned_integer_dtype, pandas_dtype
  from .dtypes import DatetimeTZDtype, ExtensionDtype, PandasExtensionDtype, PeriodDtype
  from .generic import ABCDatetimeArray, ABCDatetimeIndex, ABCPeriodArray, ABCPeriodIndex, ABCSeries
  from .inference import is_list_like
  from .missing import isna, notna
label_desc: Use image node_id 15 for calling a global function with example usage: astype_nansafe(arr, dtype, copy, skipna) and returns: arr, dtype, lib, arr, lib, tslib, arr, arr, tslibs, arr, result, arr, lib, astype_nansafe, astype_nansafe