We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
BUG: Fix QC bug in tests
Now CI is failing due to some bug on ubuntu systems

```bash
def test_qc_flag_description():
[32](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:33)
        """
[33](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:34)
        This will check if the cleanup() method will correctly convert convert
[34](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:35)
        flag_#_description to CF flag_masks and flag_meanings.
[35](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:36)
    
[36](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:37)
        """
[37](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:38)
    
[38](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:39)
        ds = read_netcdf(EXAMPLE_CO2FLX4M)
[39](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:40)
        ds.clean.cleanup()
[40](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:41)
        qc_var_name = ds.qcfilter.check_for_ancillary_qc(
[41](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:42)
            'momentum_flux', add_if_missing=False, cleanup=False
[42](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:43)
        )
[43](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:44)
    
[44](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:45)
        assert isinstance(ds[qc_var_name].attrs['flag_masks'], list)
[45](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:46)
        assert isinstance(ds[qc_var_name].attrs['flag_meanings'], list)
[46](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:47)
        assert isinstance(ds[qc_var_name].attrs['flag_assessments'], list)
[47](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:48)
        assert ds[qc_var_name].attrs['standard_name'] == 'quality_flag'
[48](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:49)
    
[49](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:50)
        assert len(ds[qc_var_name].attrs['flag_masks']) == 9
[50](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:51)
        unique_flag_assessments = list({'Acceptable', 'Indeterminate', 'Bad'})
[51](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:52)
>       assert list(set(ds[qc_var_name].attrs['flag_assessments'])) == unique_flag_assessments
[52](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:53)
E       AssertionError: assert ['Indetermina...table', 'Bad'] == ['Indetermina... 'Acceptable']
[53](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:54)
E         At index 1 diff: 'Acceptable' != 'Bad'
[54](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:55)
E         Full diff:
[55](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:56)
E         - ['Indeterminate', 'Bad', 'Acceptable']
[56](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:57)
E         ?                   -------
[57](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:58)
E         + ['Indeterminate', 'Acceptable', 'Bad']
[58](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:59)
E         ?                               +++++++
[59](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:60)

[60](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:61)
act/tests/test_qc.py:814: AssertionError
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `act/discovery/get_armfiles.py`
Content:
```
1 """
2 Script for downloading data from ARM's Live Data Webservice
3 
4 """
5 
6 import argparse
7 import json
8 import os
9 import sys
10 
11 try:
12     from urllib.request import urlopen
13 except ImportError:
14     from urllib import urlopen
15 
16 from act.utils import date_parser
17 
18 
19 def download_data(username, token, datastream, startdate, enddate, time=None, output=None):
20     """
21     This tool will help users utilize the ARM Live Data Webservice to download
22     ARM data.
23 
24     Parameters
25     ----------
26     username : str
27         The username to use for logging into the ADC archive.
28     token : str
29         The access token for accessing the ADC archive.
30     datastream : str
31         The name of the datastream to acquire.
32     startdate : str
33         The start date of the data to acquire. Formats accepted are
34         YYYY-MM-DD, DD.MM.YYYY, DD/MM/YYYY, YYYYMMDD, YYYY/MM/DD or
35         any of the previous formats with THH:MM:SS added onto the end
36         (ex. 2020-09-15T12:00:00).
37     enddate : str
38         The end date of the data to acquire. Formats accepted are
39         YYYY-MM-DD, DD.MM.YYYY, DD/MM/YYYY, YYYYMMDD or YYYY/MM/DD, or
40         any of the previous formats with THH:MM:SS added onto the end
41         (ex. 2020-09-15T13:00:00).
42     time: str or None
43         The specific time. Format is HHMMSS. Set to None to download all files
44         in the given date interval.
45     output : str
46         The output directory for the data. Set to None to make a folder in the
47         current working directory with the same name as *datastream* to place
48         the files in.
49 
50     Returns
51     -------
52     files : list
53         Returns list of files retrieved
54 
55     Notes
56     -----
57     This programmatic interface allows users to query and automate
58     machine-to-machine downloads of ARM data. This tool uses a REST URL and
59     specific parameters (saveData, query), user ID and access token, a
60     datastream name, a start date, and an end date, and data files matching
61     the criteria will be returned to the user and downloaded.
62 
63     By using this web service, users can setup cron jobs and automatically
64     download data from /data/archive into their workspace. This will also
65     eliminate the manual step of following a link in an email to download data.
66     All other data files, which are not on the spinning
67     disk (on HPSS), will have to go through the regular ordering process.
68     More information about this REST API and tools can be found on `ARM Live
69     <https://adc.arm.gov/armlive/#scripts>`_.
70 
71     To login/register for an access token click `here
72     <https://adc.arm.gov/armlive/livedata/home>`_.
73 
74     Author: Michael Giansiracusa
75     Email: giansiracumt@ornl.gov
76 
77     Web Tools Contact: Ranjeet Devarakonda zzr@ornl.gov
78 
79     Examples
80     --------
81     This code will download the netCDF files from the sgpmetE13.b1 datastream
82     and place them in a directory named sgpmetE13.b1. The data from 14 Jan to
83     20 Jan 2017 will be downloaded. Replace *userName* and *XXXXXXXXXXXXXXXX*
84     with your username and token for ARM Data Discovery. See the Notes for
85     information on how to obtain a username and token.
86 
87     .. code-block:: python
88 
89         act.discovery.download_data(
90             "userName", "XXXXXXXXXXXXXXXX", "sgpmetE13.b1", "2017-01-14", "2017-01-20"
91         )
92 
93     """
94     # default start and end are empty
95     start, end = '', ''
96     # start and end strings for query_url are constructed
97     # if the arguments were provided
98     if startdate:
99         start = date_parser(startdate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
100         start = f'&start={start}'
101     if enddate:
102         end = date_parser(enddate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
103         end = f'&end={end}'
104     # build the url to query the web service using the arguments provided
105     query_url = (
106         'https://adc.arm.gov/armlive/livedata/query?' + 'user={0}&ds={1}{2}{3}&wt=json'
107     ).format(':'.join([username, token]), datastream, start, end)
108 
109     # get url response, read the body of the message,
110     # and decode from bytes type to utf-8 string
111     response_body = urlopen(query_url).read().decode('utf-8')
112     # if the response is an html doc, then there was an error with the user
113     if response_body[1:14] == '!DOCTYPE html':
114         raise ConnectionRefusedError('Error with user. Check username or token.')
115 
116     # parse into json object
117     response_body_json = json.loads(response_body)
118 
119     # construct output directory
120     if output:
121         # output files to directory specified
122         output_dir = os.path.join(output)
123     else:
124         # if no folder given, add datastream folder
125         # to current working dir to prevent file mix-up
126         output_dir = os.path.join(os.getcwd(), datastream)
127 
128     # not testing, response is successful and files were returned
129     if response_body_json is None:
130         print('ARM Data Live Webservice does not appear to be functioning')
131         return []
132 
133     num_files = len(response_body_json['files'])
134     file_names = []
135     if response_body_json['status'] == 'success' and num_files > 0:
136         for fname in response_body_json['files']:
137             if time is not None:
138                 if time not in fname:
139                     continue
140             print(f'[DOWNLOADING] {fname}')
141             # construct link to web service saveData function
142             save_data_url = (
143                 'https://adc.arm.gov/armlive/livedata/' + 'saveData?user={0}&file={1}'
144             ).format(':'.join([username, token]), fname)
145             output_file = os.path.join(output_dir, fname)
146             # make directory if it doesn't exist
147             if not os.path.isdir(output_dir):
148                 os.makedirs(output_dir)
149             # create file and write bytes to file
150             with open(output_file, 'wb') as open_bytes_file:
151                 open_bytes_file.write(urlopen(save_data_url).read())
152             file_names.append(output_file)
153     else:
154         print(
155             'No files returned or url status error.\n' 'Check datastream name, start, and end date.'
156         )
157 
158     return file_names
159
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/act/discovery/get_armfiles.py b/act/discovery/get_armfiles.py
--- a/act/discovery/get_armfiles.py
+++ b/act/discovery/get_armfiles.py
@@ -7,6 +7,7 @@
 import json
 import os
 import sys
+from datetime import timedelta
 
 try:
     from urllib.request import urlopen
@@ -96,10 +97,15 @@
     # start and end strings for query_url are constructed
     # if the arguments were provided
     if startdate:
-        start = date_parser(startdate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
+        start_datetime = date_parser(startdate, return_datetime=True)
+        start = start_datetime.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
         start = f'&start={start}'
     if enddate:
-        end = date_parser(enddate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
+        end_datetime = date_parser(enddate, return_datetime=True)
+        # If the start and end date are the same, and a day to the end date
+        if start_datetime == end_datetime:
+            end_datetime += timedelta(days=1)
+        end = end_datetime.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
         end = f'&end={end}'
     # build the url to query the web service using the arguments provided
     query_url = (

{"golden_diff": "diff --git a/act/discovery/get_armfiles.py b/act/discovery/get_armfiles.py\n--- a/act/discovery/get_armfiles.py\n+++ b/act/discovery/get_armfiles.py\n@@ -7,6 +7,7 @@\n import json\n import os\n import sys\n+from datetime import timedelta\n \n try:\n     from urllib.request import urlopen\n@@ -96,10 +97,15 @@\n     # start and end strings for query_url are constructed\n     # if the arguments were provided\n     if startdate:\n-        start = date_parser(startdate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n+        start_datetime = date_parser(startdate, return_datetime=True)\n+        start = start_datetime.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n         start = f'&start={start}'\n     if enddate:\n-        end = date_parser(enddate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n+        end_datetime = date_parser(enddate, return_datetime=True)\n+        # If the start and end date are the same, and a day to the end date\n+        if start_datetime == end_datetime:\n+            end_datetime += timedelta(days=1)\n+        end = end_datetime.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n         end = f'&end={end}'\n     # build the url to query the web service using the arguments provided\n     query_url = (\n", "issue": "BUG: Fix QC bug in tests\nNow CI is failing due to some bug on ubuntu systems\r\n\r\n```bash\r\ndef test_qc_flag_description():\r\n[32](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:33)\r\n        \"\"\"\r\n[33](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:34)\r\n        This will check if the cleanup() method will correctly convert convert\r\n[34](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:35)\r\n        flag_#_description to CF flag_masks and flag_meanings.\r\n[35](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:36)\r\n    \r\n[36](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:37)\r\n        \"\"\"\r\n[37](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:38)\r\n    \r\n[38](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:39)\r\n        ds = read_netcdf(EXAMPLE_CO2FLX4M)\r\n[39](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:40)\r\n        ds.clean.cleanup()\r\n[40](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:41)\r\n        qc_var_name = ds.qcfilter.check_for_ancillary_qc(\r\n[41](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:42)\r\n            'momentum_flux', add_if_missing=False, cleanup=False\r\n[42](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:43)\r\n        )\r\n[43](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:44)\r\n    \r\n[44](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:45)\r\n        assert isinstance(ds[qc_var_name].attrs['flag_masks'], list)\r\n[45](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:46)\r\n        assert isinstance(ds[qc_var_name].attrs['flag_meanings'], list)\r\n[46](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:47)\r\n        assert isinstance(ds[qc_var_name].attrs['flag_assessments'], list)\r\n[47](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:48)\r\n        assert ds[qc_var_name].attrs['standard_name'] == 'quality_flag'\r\n[48](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:49)\r\n    \r\n[49](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:50)\r\n        assert len(ds[qc_var_name].attrs['flag_masks']) == 9\r\n[50](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:51)\r\n        unique_flag_assessments = list({'Acceptable', 'Indeterminate', 'Bad'})\r\n[51](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:52)\r\n>       assert list(set(ds[qc_var_name].attrs['flag_assessments'])) == unique_flag_assessments\r\n[52](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:53)\r\nE       AssertionError: assert ['Indetermina...table', 'Bad'] == ['Indetermina... 'Acceptable']\r\n[53](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:54)\r\nE         At index 1 diff: 'Acceptable' != 'Bad'\r\n[54](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:55)\r\nE         Full diff:\r\n[55](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:56)\r\nE         - ['Indeterminate', 'Bad', 'Acceptable']\r\n[56](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:57)\r\nE         ?                   -------\r\n[57](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:58)\r\nE         + ['Indeterminate', 'Acceptable', 'Bad']\r\n[58](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:59)\r\nE         ?                               +++++++\r\n[59](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:60)\r\n\r\n[60](https://github.com/ARM-DOE/ACT/runs/7508339706?check_suite_focus=true#step:6:61)\r\nact/tests/test_qc.py:814: AssertionError\r\n```\n", "before_files": [{"content": "\"\"\"\nScript for downloading data from ARM's Live Data Webservice\n\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport sys\n\ntry:\n    from urllib.request import urlopen\nexcept ImportError:\n    from urllib import urlopen\n\nfrom act.utils import date_parser\n\n\ndef download_data(username, token, datastream, startdate, enddate, time=None, output=None):\n    \"\"\"\n    This tool will help users utilize the ARM Live Data Webservice to download\n    ARM data.\n\n    Parameters\n    ----------\n    username : str\n        The username to use for logging into the ADC archive.\n    token : str\n        The access token for accessing the ADC archive.\n    datastream : str\n        The name of the datastream to acquire.\n    startdate : str\n        The start date of the data to acquire. Formats accepted are\n        YYYY-MM-DD, DD.MM.YYYY, DD/MM/YYYY, YYYYMMDD, YYYY/MM/DD or\n        any of the previous formats with THH:MM:SS added onto the end\n        (ex. 2020-09-15T12:00:00).\n    enddate : str\n        The end date of the data to acquire. Formats accepted are\n        YYYY-MM-DD, DD.MM.YYYY, DD/MM/YYYY, YYYYMMDD or YYYY/MM/DD, or\n        any of the previous formats with THH:MM:SS added onto the end\n        (ex. 2020-09-15T13:00:00).\n    time: str or None\n        The specific time. Format is HHMMSS. Set to None to download all files\n        in the given date interval.\n    output : str\n        The output directory for the data. Set to None to make a folder in the\n        current working directory with the same name as *datastream* to place\n        the files in.\n\n    Returns\n    -------\n    files : list\n        Returns list of files retrieved\n\n    Notes\n    -----\n    This programmatic interface allows users to query and automate\n    machine-to-machine downloads of ARM data. This tool uses a REST URL and\n    specific parameters (saveData, query), user ID and access token, a\n    datastream name, a start date, and an end date, and data files matching\n    the criteria will be returned to the user and downloaded.\n\n    By using this web service, users can setup cron jobs and automatically\n    download data from /data/archive into their workspace. This will also\n    eliminate the manual step of following a link in an email to download data.\n    All other data files, which are not on the spinning\n    disk (on HPSS), will have to go through the regular ordering process.\n    More information about this REST API and tools can be found on `ARM Live\n    <https://adc.arm.gov/armlive/#scripts>`_.\n\n    To login/register for an access token click `here\n    <https://adc.arm.gov/armlive/livedata/home>`_.\n\n    Author: Michael Giansiracusa\n    Email: giansiracumt@ornl.gov\n\n    Web Tools Contact: Ranjeet Devarakonda zzr@ornl.gov\n\n    Examples\n    --------\n    This code will download the netCDF files from the sgpmetE13.b1 datastream\n    and place them in a directory named sgpmetE13.b1. The data from 14 Jan to\n    20 Jan 2017 will be downloaded. Replace *userName* and *XXXXXXXXXXXXXXXX*\n    with your username and token for ARM Data Discovery. See the Notes for\n    information on how to obtain a username and token.\n\n    .. code-block:: python\n\n        act.discovery.download_data(\n            \"userName\", \"XXXXXXXXXXXXXXXX\", \"sgpmetE13.b1\", \"2017-01-14\", \"2017-01-20\"\n        )\n\n    \"\"\"\n    # default start and end are empty\n    start, end = '', ''\n    # start and end strings for query_url are constructed\n    # if the arguments were provided\n    if startdate:\n        start = date_parser(startdate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n        start = f'&start={start}'\n    if enddate:\n        end = date_parser(enddate, output_format='%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n        end = f'&end={end}'\n    # build the url to query the web service using the arguments provided\n    query_url = (\n        'https://adc.arm.gov/armlive/livedata/query?' + 'user={0}&ds={1}{2}{3}&wt=json'\n    ).format(':'.join([username, token]), datastream, start, end)\n\n    # get url response, read the body of the message,\n    # and decode from bytes type to utf-8 string\n    response_body = urlopen(query_url).read().decode('utf-8')\n    # if the response is an html doc, then there was an error with the user\n    if response_body[1:14] == '!DOCTYPE html':\n        raise ConnectionRefusedError('Error with user. Check username or token.')\n\n    # parse into json object\n    response_body_json = json.loads(response_body)\n\n    # construct output directory\n    if output:\n        # output files to directory specified\n        output_dir = os.path.join(output)\n    else:\n        # if no folder given, add datastream folder\n        # to current working dir to prevent file mix-up\n        output_dir = os.path.join(os.getcwd(), datastream)\n\n    # not testing, response is successful and files were returned\n    if response_body_json is None:\n        print('ARM Data Live Webservice does not appear to be functioning')\n        return []\n\n    num_files = len(response_body_json['files'])\n    file_names = []\n    if response_body_json['status'] == 'success' and num_files > 0:\n        for fname in response_body_json['files']:\n            if time is not None:\n                if time not in fname:\n                    continue\n            print(f'[DOWNLOADING] {fname}')\n            # construct link to web service saveData function\n            save_data_url = (\n                'https://adc.arm.gov/armlive/livedata/' + 'saveData?user={0}&file={1}'\n            ).format(':'.join([username, token]), fname)\n            output_file = os.path.join(output_dir, fname)\n            # make directory if it doesn't exist\n            if not os.path.isdir(output_dir):\n                os.makedirs(output_dir)\n            # create file and write bytes to file\n            with open(output_file, 'wb') as open_bytes_file:\n                open_bytes_file.write(urlopen(save_data_url).read())\n            file_names.append(output_file)\n    else:\n        print(\n            'No files returned or url status error.\\n' 'Check datastream name, start, and end date.'\n        )\n\n    return file_names\n", "path": "act/discovery/get_armfiles.py"}], "after_files": [{"content": "\"\"\"\nScript for downloading data from ARM's Live Data Webservice\n\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport sys\nfrom datetime import timedelta\n\ntry:\n    from urllib.request import urlopen\nexcept ImportError:\n    from urllib import urlopen\n\nfrom act.utils import date_parser\n\n\ndef download_data(username, token, datastream, startdate, enddate, time=None, output=None):\n    \"\"\"\n    This tool will help users utilize the ARM Live Data Webservice to download\n    ARM data.\n\n    Parameters\n    ----------\n    username : str\n        The username to use for logging into the ADC archive.\n    token : str\n        The access token for accessing the ADC archive.\n    datastream : str\n        The name of the datastream to acquire.\n    startdate : str\n        The start date of the data to acquire. Formats accepted are\n        YYYY-MM-DD, DD.MM.YYYY, DD/MM/YYYY, YYYYMMDD, YYYY/MM/DD or\n        any of the previous formats with THH:MM:SS added onto the end\n        (ex. 2020-09-15T12:00:00).\n    enddate : str\n        The end date of the data to acquire. Formats accepted are\n        YYYY-MM-DD, DD.MM.YYYY, DD/MM/YYYY, YYYYMMDD or YYYY/MM/DD, or\n        any of the previous formats with THH:MM:SS added onto the end\n        (ex. 2020-09-15T13:00:00).\n    time: str or None\n        The specific time. Format is HHMMSS. Set to None to download all files\n        in the given date interval.\n    output : str\n        The output directory for the data. Set to None to make a folder in the\n        current working directory with the same name as *datastream* to place\n        the files in.\n\n    Returns\n    -------\n    files : list\n        Returns list of files retrieved\n\n    Notes\n    -----\n    This programmatic interface allows users to query and automate\n    machine-to-machine downloads of ARM data. This tool uses a REST URL and\n    specific parameters (saveData, query), user ID and access token, a\n    datastream name, a start date, and an end date, and data files matching\n    the criteria will be returned to the user and downloaded.\n\n    By using this web service, users can setup cron jobs and automatically\n    download data from /data/archive into their workspace. This will also\n    eliminate the manual step of following a link in an email to download data.\n    All other data files, which are not on the spinning\n    disk (on HPSS), will have to go through the regular ordering process.\n    More information about this REST API and tools can be found on `ARM Live\n    <https://adc.arm.gov/armlive/#scripts>`_.\n\n    To login/register for an access token click `here\n    <https://adc.arm.gov/armlive/livedata/home>`_.\n\n    Author: Michael Giansiracusa\n    Email: giansiracumt@ornl.gov\n\n    Web Tools Contact: Ranjeet Devarakonda zzr@ornl.gov\n\n    Examples\n    --------\n    This code will download the netCDF files from the sgpmetE13.b1 datastream\n    and place them in a directory named sgpmetE13.b1. The data from 14 Jan to\n    20 Jan 2017 will be downloaded. Replace *userName* and *XXXXXXXXXXXXXXXX*\n    with your username and token for ARM Data Discovery. See the Notes for\n    information on how to obtain a username and token.\n\n    .. code-block:: python\n\n        act.discovery.download_data(\n            \"userName\", \"XXXXXXXXXXXXXXXX\", \"sgpmetE13.b1\", \"2017-01-14\", \"2017-01-20\"\n        )\n\n    \"\"\"\n    # default start and end are empty\n    start, end = '', ''\n    # start and end strings for query_url are constructed\n    # if the arguments were provided\n    if startdate:\n        start_datetime = date_parser(startdate, return_datetime=True)\n        start = start_datetime.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n        start = f'&start={start}'\n    if enddate:\n        end_datetime = date_parser(enddate, return_datetime=True)\n        # If the start and end date are the same, and a day to the end date\n        if start_datetime == end_datetime:\n            end_datetime += timedelta(days=1)\n        end = end_datetime.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n        end = f'&end={end}'\n    # build the url to query the web service using the arguments provided\n    query_url = (\n        'https://adc.arm.gov/armlive/livedata/query?' + 'user={0}&ds={1}{2}{3}&wt=json'\n    ).format(':'.join([username, token]), datastream, start, end)\n\n    # get url response, read the body of the message,\n    # and decode from bytes type to utf-8 string\n    response_body = urlopen(query_url).read().decode('utf-8')\n    # if the response is an html doc, then there was an error with the user\n    if response_body[1:14] == '!DOCTYPE html':\n        raise ConnectionRefusedError('Error with user. Check username or token.')\n\n    # parse into json object\n    response_body_json = json.loads(response_body)\n\n    # construct output directory\n    if output:\n        # output files to directory specified\n        output_dir = os.path.join(output)\n    else:\n        # if no folder given, add datastream folder\n        # to current working dir to prevent file mix-up\n        output_dir = os.path.join(os.getcwd(), datastream)\n\n    # not testing, response is successful and files were returned\n    if response_body_json is None:\n        print('ARM Data Live Webservice does not appear to be functioning')\n        return []\n\n    num_files = len(response_body_json['files'])\n    file_names = []\n    if response_body_json['status'] == 'success' and num_files > 0:\n        for fname in response_body_json['files']:\n            if time is not None:\n                if time not in fname:\n                    continue\n            print(f'[DOWNLOADING] {fname}')\n            # construct link to web service saveData function\n            save_data_url = (\n                'https://adc.arm.gov/armlive/livedata/' + 'saveData?user={0}&file={1}'\n            ).format(':'.join([username, token]), fname)\n            output_file = os.path.join(output_dir, fname)\n            # make directory if it doesn't exist\n            if not os.path.isdir(output_dir):\n                os.makedirs(output_dir)\n            # create file and write bytes to file\n            with open(output_file, 'wb') as open_bytes_file:\n                open_bytes_file.write(urlopen(save_data_url).read())\n            file_names.append(output_file)\n    else:\n        print(\n            'No files returned or url status error.\\n' 'Check datastream name, start, and end date.'\n        )\n\n    return file_names\n", "path": "act/discovery/get_armfiles.py"}]}