Repository: crsmithdev/arrow
Pull request #746 (2020-01-01 22:06:30)

Fixed arrow.get with a timestamp and a timezone string
Replaces: https://github.com/crsmithdev/arrow/pull/744

codecov-io: # [Codecov](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=h1) Report
> Merging [#746](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=desc) into [master](https://codecov.io/gh/crsmithdev/arrow/commit/6a70b9d11372865d8e9dc67f20ca5f165adf0719?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/crsmithdev/arrow/pull/746/graphs/tree.svg?width=650&token=4EkGnFsIGn&height=150&src=pr)](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master   #746   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           9      9           
  Lines        1649   1667   +18     
  Branches      279    281    +2     
=====================================
+ Hits         1649   1667   +18
```


| [Impacted Files](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [arrow/util.py](https://codecov.io/gh/crsmithdev/arrow/pull/746/diff?src=pr&el=tree#diff-YXJyb3cvdXRpbC5weQ==) | `100% <100%> (ø)` | :arrow_up: |
| [arrow/arrow.py](https://codecov.io/gh/crsmithdev/arrow/pull/746/diff?src=pr&el=tree#diff-YXJyb3cvYXJyb3cucHk=) | `100% <100%> (ø)` | :arrow_up: |
| [arrow/parser.py](https://codecov.io/gh/crsmithdev/arrow/pull/746/diff?src=pr&el=tree#diff-YXJyb3cvcGFyc2VyLnB5) | `100% <0%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=footer). Last update [6a70b9d...09fe817](https://codecov.io/gh/crsmithdev/arrow/pull/746?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.travis.yml b/.travis.yml
index b86f51b..e549ef4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,13 +24,13 @@ matrix:
           os: windows
           language: shell # 'language: python' is an error on Travis CI Windows
           before_install:
-              - choco install python --version 3.7.4
+              - choco install python --version 3.7.5
               - python -m pip install --upgrade pip
           env:
               - PATH=/c/Python37:/c/Python37/Scripts:$PATH
               - TOXENV=py37
         - name: "Python 3.8"
-          python: "3.8-dev"
+          python: "3.8"
           env: TOXENV=py38
         - name: "Linting"
           python: "3.7"
diff --git a/arrow/arrow.py b/arrow/arrow.py
index 89c3e50..1099a6d 100644
--- a/arrow/arrow.py
+++ b/arrow/arrow.py
@@ -146,16 +146,12 @@ class Arrow(object):
 
         :param timestamp: an ``int`` or ``float`` timestamp, or a ``str`` that converts to either.
         :param tzinfo: (optional) a ``tzinfo`` object.  Defaults to local time.
-
-        Timestamps should always be UTC. If you have a non-UTC timestamp::
-
-            >>> arrow.Arrow.utcfromtimestamp(1367900664).replace(tzinfo='US/Pacific')
-            <Arrow [2013-05-07T04:24:24-07:00]>
-
         """
 
         if tzinfo is None:
             tzinfo = dateutil_tz.tzlocal()
+        elif util.isstr(tzinfo):
+            tzinfo = parser.TzinfoParser.parse(tzinfo)
 
         if not util.is_timestamp(timestamp):
             raise ValueError(
@@ -1423,19 +1419,17 @@ class Arrow(object):
 
     @classmethod
     def _get_datetime(cls, expr):
-
+        """Get datetime object for a specified expression."""
         if isinstance(expr, Arrow):
             return expr.datetime
-
-        if isinstance(expr, datetime):
+        elif isinstance(expr, datetime):
             return expr
-
-        try:
-            expr = float(expr)
-            return cls.utcfromtimestamp(expr).datetime
-        except Exception:
+        elif util.is_timestamp(expr):
+            timestamp = float(expr)
+            return cls.utcfromtimestamp(timestamp).datetime
+        else:
             raise ValueError(
-                "'{}' not recognized as a timestamp or datetime".format(expr)
+                "'{}' not recognized as a datetime or timestamp.".format(expr)
             )
 
     @classmethod
diff --git a/arrow/util.py b/arrow/util.py
index 62f1a05..7037f1f 100644
--- a/arrow/util.py
+++ b/arrow/util.py
@@ -4,7 +4,8 @@ from __future__ import absolute_import
 import datetime
 
 
-def total_seconds(td):  # pragma: no cover
+def total_seconds(td):
+    """Get total seconds for timedelta."""
     return td.total_seconds()
 
 


Test patch:
diff --git a/tests/arrow_tests.py b/tests/arrow_tests.py
index 061ed20..c358329 100644
--- a/tests/arrow_tests.py
+++ b/tests/arrow_tests.py
@@ -103,6 +103,12 @@ class ArrowFactoryTests(Chai):
             datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")),
         )
 
+        result = arrow.Arrow.fromtimestamp(timestamp, tzinfo="Europe/Paris")
+        assertDtEqual(
+            result._datetime,
+            datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")),
+        )
+
         with self.assertRaises(ValueError):
             arrow.Arrow.fromtimestamp("invalid timestamp")
 
diff --git a/tests/util_tests.py b/tests/util_tests.py
index bb84c44..804ae62 100644
--- a/tests/util_tests.py
+++ b/tests/util_tests.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 import time
+from datetime import datetime
 
 from chai import Chai
 
@@ -7,6 +8,10 @@ from arrow import util
 
 
 class UtilTests(Chai):
+    def test_total_seconds(self):
+        td = datetime(2019, 1, 1) - datetime(2018, 1, 1)
+        self.assertEqual(util.total_seconds(td), td.total_seconds())
+
     def test_is_timestamp(self):
         timestamp_float = time.time()
         timestamp_int = int(timestamp_float)