1
0
Fork 0
Commit graph

200 commits

Author SHA1 Message Date
Florent Rougon
c30298ffce terrasync.py: add option --only-subdir
Option --only-subdir allows one to restrict terrasync.py processing[1]
to a chosen subdirectory of the TerraSync repository. Example:

  terrasync.py --target=/your/TerraSync/repo --only-subdir="Airports/L/F/P"

[1] This works in both 'check' and 'sync' modes.
2018-02-07 11:38:41 +01:00
Florent Rougon
c0e1f29a75 terrasync.py: add and use a VirtualPath class; also add MutableVirtualPath
Add classes VirtualPath and MutableVirtualPath (the latter derived from
the former) to manipulate slash-separated paths where the root '/'
represents the TerraScenery root. This makes it clear what a function
expects when you see that one of its arguments is a VirtualPath
instance: you don't have to ask yourself whether it can start or end
with a slash, how to interpret it, etc. Operating on these paths is also
easy[1], be it to assemble URLs in order to retrieve files or to join
their relative part with a local directory path in order to obtain a
real (deeper) local path.

VirtualPath and MutableVirtualPath are essentially the same; the former
is hashable and therefore has to be immutable, whereas the latter can be
modified in-place with the /= operator (used to append path components),
and therefore can't be hashable. As a consequence, MutableVirtualPath
instances can't be used as dictionary keys, elements of a set or
frozenset, etc.

VirtualPath and MutableVirtualPath use the pathlib.PurePath API where
applicable (part of this API has been implemented in
[Mutable]VirtualPath; more can be added, of course). These classes have
no assumptions related to TerraSync and thus should be fit for use in
other projects.

To convert a [Mutable]VirtualPath instance to a string, just use str()
on it. The result is guaranteed to start with a '/' and not to end with
a '/', except for the virtual root '/'. Upon construction, the given
string is interpreted relatively to the virtual root, i.e.:

  VirtualPath("") == VirtualPath("/")
  VirtualPath("abc/def/ghi") == VirtualPath("/abc/def/ghi")
  etc.

VirtualPath and MutableVirtualPath instances sort like the respective
strings str() converts them too. The __hash__() method of VirtualPath is
based on the type and this string representation, too. Such objects can
only compare equal (using ==) if they have the same type. If you want to
compare the underlying virtual paths inside a VirtualPath and a
MutableVirtualPath, use the samePath() method of either class.

For more info, see scripts/python/TerraSync/terrasync/virtual_path.py
and unit tests in scripts/python/TerraSync/tests/test_virtual_path.py.

[1] Most useful is the / operator, which works as for SGPath:

      VirtualPath("/abc/def/ghi") == VirtualPath("/abc") / "def" / "ghi"
      VirtualPath("/abc/def/ghi") == VirtualPath("/abc") / "def/ghi"
2018-02-07 11:38:41 +01:00
Florent Rougon
e613c81b4c terrasync.py: move custom exception classes to a separate module
Add new module 'terrasync.exceptions' for our custom exception classes.
2018-02-07 11:38:41 +01:00
Florent Rougon
c72de824d2 terrasync.py: more modular code layout
- New directory scripts/python/TerraSync/terrasync.

- Move scripts/python/terrasync.py to
  scripts/python/TerraSync/terrasync/main.py (main module in the new
  structure).

- Add empty __init__.py file to scripts/python/TerraSync/terrasync/ to
  make this directory a Python package.

- Wrap the main code from previous terrasync.py in a main() function of
  the terrasync.main module. Also move command-line arguments parsing to
  a separate parseCommandLine() function.

- Add an executable script scripts/python/TerraSync/terrasync.py for end
  users, that just calls terrasync.main.main().

For end users, the only difference is that they now have to use
scripts/python/TerraSync/terrasync.py instead of
scripts/python/terrasync.py (which doesn't exist anymore, since all this
lives under the scripts/python/TerraSync directory from now on).

This structure will allow to cleanly split the code into modules and to
add unit tests.
2018-02-07 11:38:41 +01:00
Florent Rougon
eb23f8906d terrasync.py: use os.path.abspath() in TerraSync.setTarget()
Using os.path.abspath() here in TerraSync.setTarget() adds a safety
layer in case the process later calls os.chdir() or similar[1], which
would change the meaning of the "." directory. Also remove the strip()
call which I don't consider useful here, see my message at:

  https://sourceforge.net/p/flightgear/mailman/message/36208140/

[1] Not the case currently, but who knows what will happen in the
    future...
2018-02-03 11:22:56 +01:00
Florent Rougon
77513a2498 terrasync.py: update script header
In particular, terrasync.py appears *not* to require dnspython. :-)
2018-02-03 11:22:56 +01:00
Florent Rougon
8693e442d7 terrasync.py: add options --mode and --report
You may now call terrasync.py with --mode=sync or --mode=check. 'sync'
mode is the default and corresponds to terrasync.py's usual behavior.

In 'check' mode, terrasync.py never writes to disk and aborts at the
first mismatch between local and remote data. The exit status in 'check'
mode is:
  - 0 if the program terminated successfully and no mismatch was found
    between the local and remote repositories;
  - 1 in case an error was encountered;
  - 2 if there was a mismatch between local and remote data.

In 'sync' mode, the exit status is:
  - 0 if the program terminated successfully;
  - 1 in case an error was encountered.

A mismatch in 'check' mode is *not* an error, it is just one of the two
expected results. An error is a worse condition (uncaught exception,
network retrieval aborted after retrying failed, stuff like that).

Additionally, calling terrasync.py with --report causes it to print
lists of:
  - files and dirs that were missing or had mismatching hashes (this is
    okay in 'sync' mode: these things have been "fixed" in the target
    directory before the report was printed);
  - files and dirs that have been found to be orphaned (i.e., found
    under the target directory but not mentioned in the corresponding
    .dirindex file). These are the ones removed in 'sync' mode when
    --remove-orphan is passed.
2018-02-03 11:22:56 +01:00
Florent Rougon
6d323bbbdc terrasync.py: prepare the terrain for --mode and --report
- Add computeHash() utility function that can work with any file-like
  object (e.g., a connected socket).

- Rename hash_of_file() to hashForFile(), and of course implement it
  using our new computeHash().

- Add class HTTPSocketRequest derived from HTTPGetCallback. It allows
  one to process data from the network without storing it to a file (it
  uses the file-like interface provided by http.client.HTTPResponse).

  The callback returns the http.client.HTTPResponse object, which can be
  conveniently used in a 'with' statement.

- Simplify the API of TerraSync.updateDirectory(): its 'dirIndexHash'
  argument must now be a hash (a string); the None object is not allowed
  anymore (with the soon-to-come addition of --mode=check, having to
  deal with this special case in updateDirectory() would make the logic
  too difficult to follow, or we would have to really completely
  separate check-only mode from update mode, which would entail code
  duplication).

  Since TerraSync.updateDirectory() must now always have a hash to work
  with, compute the hash of the root '.dirindex' file from the server in
  TerraSync.start(), using our new HTTPSocketRequest class---which was
  written for this purpose, since that will have to work in check-only
  mode (but not only), where we don't want to write any file to disk.

- TerraSync.updateFile(): correctly handle the case where a directory
  inside the TerraSync repository is (now) a file according to the
  server: the directory must be recursively removed before the file can
  be downloaded in the place formerly occupied by the directory.

- Add stub class Report. Its methods do nothing for now, but are already
  called in a couple of appropriate places. The class will be completed
  in a future commit, of course.
2018-02-03 11:22:56 +01:00
Florent Rougon
af021cc1ef terrasync.py: add function removeDirectoryTree() and exception UserError
The goal of removeDirectoryTree() is to provide a safety net around
recursive directory removal with shutil.rmtree(), in order to prevent
user or bug-caused catastrophic events such as /, /home /home/joeuser or
C:\ being recursively erased.
2018-02-03 11:22:56 +01:00
Florent Rougon
2c6f93aa46 terrasync.py: improve retry logic and error handling
- Add method assembleUrl() to HTTPGetter.

- Raise a NetworkError exception with the particular URL and number of
  retries when it has been exhausted.

- Number of retries is now trivial to expose as a parameter, and set to
  5 in HTTPGetter.

- Sleep for one second between self.httpConnection.close() and
  self.httpConnection.connect() when retrying a failed HTTP request.

- Apply DRY principle.
2018-02-03 11:22:56 +01:00
Florent Rougon
c27ae92c73 terrasync.py: improve error handling
- New generic exception class TerraSyncPyException.

- Add subclass NetworkError of TerraSyncPyException.

- Raise a NetworkError exception when the HTTP return code is not 200.

- hash_of_file() does not silently ignore errors anymore; exceptions
  should be dealt with wherever appropriate by the callers.

  Whenever hash_of_file() returns, its return value is now the SHA-1
  hash of the specified file. This is less error-prone IMHO than
  returning None. Otherwise, calling code could erroneously conclude
  that there is a matching hash when the file to check is actually
  missing. For a concrete example, see the 'dirIndexHash' parameter of
  TerraSync.updateDirectory(), which so far is used precisely with the
  value None to express that "we are just starting the recursion and
  have no hash from the server to compare to".
2018-02-03 11:22:56 +01:00
Florent Rougon
19209a71f0 terrasync.py: improve the HTTPGetter and HTTPGetCallback APIs
When called, the callback passed to HTTPGetter.get() is now explicitly
passed the URL and the http.client.HTTPResponse instance.

Remove the HTTPGetCallback.result attribute (not needed anymore, leaves
more freedom when implementating HTTPGetCallback subclasses...).
2018-02-03 11:22:56 +01:00
Florent Rougon
de4291b851 terrasync.py: make HTTPGetter.get() return the HTTPGetCallback.callback ret value
This way, the caller can get access to interesting things from the
callback, such as the HTTPResponse object (wrapper for the socket).
2018-02-03 11:22:56 +01:00
Florent Rougon
b7fc63d896 terrasync.py: remove methods TerraSync.isReady() and TerraSync.update()
These methods don't work, because HTTPGetter objects have no isReady()
and update() methods either.
2018-02-03 11:22:56 +01:00
Florent Rougon
417d81d4c3 terrasync.py: minor changes
These changes should not alter the behavior of terrasync.py.
2018-02-03 11:22:56 +01:00
Torsten Dreyer
a27ea4dfe6 remove orphan directories with --remove-orphan 2017-09-01 10:33:35 +02:00
Alessandro Menti
7245357751
Mark enhanced lighting options and --adf as deprecated
Print an error message and exit if --{enable,disable}-enhanced-lighting
or --adf are used (those deprecated options will be removed in a future
version of FlightGear).
2017-06-04 16:56:17 +02:00
Alessandro Menti
f1ffe97991
Add CMake Linux install directives for the icons and the .desktop file 2017-05-24 22:47:01 +02:00
Saikrishna Arcot
bb0869599b
Switch to using argparse in terrasync.py, which is actually maintained, and fix a couple of errors. 2016-12-28 08:32:55 -06:00
Saikrishna Arcot
eb4738cb02
Switch to using optparse module, and allow settings bounds from command line. 2016-12-27 22:41:59 -06:00
Saikrishna Arcot
e67ea4e0cb
Add in the ability to download scenery only for a specific section. 2016-12-27 21:17:46 -06:00
Saikrishna Arcot
2c5429c589
Improve error handling.
If the response to the HTTP request isn't 200 (success), then don't save
the response, and don't call the callback.

Additionally, only retry in the case of HTTPException. This allows using
Ctrl-C to work correctly (and easily).
2016-12-27 20:46:59 -06:00
Torsten Dreyer
b9cba13e32 Fix the root cause for terrasync.py timeouts
Thanks to Andre Coetzee for spotting.

Also, don't hardcode port 80, intead use the port given in the url
2016-06-06 12:17:12 +02:00
Torsten Dreyer
a93dd29c85 First attempt to handle the nasty socket timeout
Retry once if a http get fails
2016-05-25 16:19:36 +02:00
Torsten Dreyer
489be2ce16 Add user-agent request header 2016-05-18 15:14:59 +02:00
Torsten Dreyer
6921c98933 Much better terrasync.py
- tortellini instead of spaghetti code (use oop)
- reuse connection
2016-05-18 12:51:29 +02:00
Torsten Dreyer
e2afbb4678 terrasync.py: cleanup and add some more power
- add option --quick
  check sha1sum of .dirindex files and skip directory if hash matches
- add option --remove-orphan
  remove orphan files (files exist locally but not on server)
- be less verbose
- write .dirindex files locally
2016-05-11 23:04:24 +02:00
Torsten Dreyer
0c5e99504d Move terrasync.py to /scripts/python 2016-05-11 14:59:36 +02:00
Raphael Dümig
a59e04ff36 replaced the outdated bash completion script with a completely rewritten version
The new script is documented in the flightgear wiki (see "bash completion") and adds functionality such as advanced detection of FG_ROOT and other paths, and many completions not available before.
The list of possible command line options is automatically generated from "fgfs --help --verbose".

The author of the original script (mfranz) has agreed to replace this script.
2014-10-08 14:36:39 +02:00
Gijs de Rooy
8c99d5d9d6 Remove unused --control option 2014-06-19 14:28:14 +02:00
Thomas Geymayer
d6ba7b0040 gedit syntaxhighlight/snippet support for Nasal.
Files by Philosopher: http://forum.flightgear.org/viewtopic.php\?f\=30\&t\=17265\#p164133
2013-11-07 14:30:03 +01:00
ThorstenB
3bf09215b0 Update ATIS voice generation scripts
Split voice samples into two separate files (airport and phraseology).
Compress voice samples.
2012-10-13 15:45:15 +02:00
ThorstenB
2d424062b7 Original ATIS voice generation scripts by John Denker
Also thanks to Dave Luff for digging this up from his (t)rusty hard disk.
2012-10-13 15:45:15 +02:00
ThorstenB
02b160c5ff #718: java client example not compiling
Util.java was added to the repo commenting "Half-finished utility class.".
No more progress since (10 years!), so just exclude the file from the
java build by changing its extension.
2012-03-27 21:06:29 +02:00
ThorstenB
924468169d Ignore empty lines in html output. 2012-03-25 10:34:50 +02:00
ThorstenB
8b46ee6648 Adapt script to changed name. 2012-03-04 19:49:28 +01:00
ThorstenB
7d2f2f2b6f Rename to "nasal_api_doc.py". 2012-03-04 19:49:02 +01:00
ThorstenB
8ce0c041ae Ignore .pyc files
(compiled python binaries)
2012-03-04 19:40:19 +01:00
adrian
3c233131f2 updated API script 2012-03-04 19:36:07 +01:00
adrian
39e399d8ec python script which generates $FGROOT/Nasal API documentation 2012-03-04 19:36:07 +01:00
James Turner
70b4f38ebc Goodbye automake. 2011-11-01 11:15:53 +00:00
Durk Talsma
c6feba04c9 Make the script a little more general purpose usable by removing a hardcoded filename. 2011-01-03 13:58:12 +01:00
Durk Talsma
6c165c30f2 Change file permissions to make the scripts executable. 2011-01-03 13:06:12 +01:00
Durk Talsma
dcfa2632fb Traffic tools. Conversion scripts to convert between xml and plain text format. Initial version of conf2xml.pl by me. Updated and modified by Mike Nieber. xml2conf.pl by Mike Nieber. 2011-01-03 09:59:48 +01:00
James Turner
5bb247d40a Fix syntax for IF DEFINED conditionals 2010-11-14 23:32:37 +00:00
James Turner
9bf4c887d4 Windows version.h generation script. 2010-11-14 23:26:27 +00:00
Christian Schmitt
0a5e86f4e6 remove old .cvsignore files 2010-11-11 01:16:29 +01:00
curt
c74cdade0b Be compatible with newer versions of tail and gnuplot. 2009-04-15 23:19:30 +02:00
curt
3b478871dd newest gnuplot doesn't like the "set terminal png color" command,
change to "set terminal png"
2009-04-15 23:19:30 +02:00
mfranz
4e13f8e4a0 nasal syntax: handle bracket error correctly 2009-03-18 08:00:09 +01:00
mfranz
7fd6f68c4e nasal.vim: add getAliasTarget clearValue, values, io.flush 2009-02-16 00:56:44 +01:00
mfranz
6fa20b5903 revert to using a cached list of aircraft -- scanning the Aircraft/
dirs is only fast enough with hot file-cache, but a bit too painful
otherwise. Updating the aircraft.list is now easier, though: Just
type   $ fgfs --aircraft=?<TAB>
2008-12-20 23:24:50 +00:00
mfranz
a9667c129c better instructions 2008-12-20 12:50:03 +00:00
mfranz
f382f053ff live-compile aircraft list, instead of requiring to build it
regularly. That's fast enough.
2008-12-20 10:32:42 +00:00
mfranz
29be38ed2a mark file names (for post-processing) 2008-12-19 13:38:25 +00:00
mfranz
404c3c863a include png and xcf files by default 2008-12-13 20:17:02 +00:00
mfranz
301915a05f add props.Node.{initNode,alias,unalias} 2008-11-20 20:11:46 +00:00
mfranz
d612706304 Move vim syntax files from utils/syntax/ to scripts/syntax/. They aren't
exactly scripts, but neither are they utilities by themselves. And the
neighbourship to the completion scripts makes sense (IMHO).
2008-10-13 21:22:10 +00:00
mfranz
1c60d4b205 completion: move scripts from tools/ to completion/ 2008-10-06 13:26:51 +00:00
mfranz
c248528c6f Nicolas: zsh completion script 2008-10-01 11:32:06 +00:00
mfranz
0d89cb9073 - remove redundant command
- better alignment of help screen
2008-09-23 20:21:19 +00:00
mfranz
9d3941ae1b lsprop: version math.pi (change %'v -> %q and %"V -> %Q; cosmetics) 2008-08-19 11:13:07 +00:00
mfranz
1a2dd7e63e lsprop: make included paths absolute 2008-08-19 06:52:47 +00:00
mfranz
9c2b9af40d lsprop: also consider includes from <PropertyList>; help improvements 2008-08-19 06:36:48 +00:00
mfranz
3da291dde6 lsprop: fix -p long option 2008-08-18 13:12:31 +00:00
mfranz
9959b08698 XMLErrors on one line 2008-08-18 10:15:39 +00:00
mfranz
1c4e485d12 lsprop: list properties of <PropertyList> XML files 2008-08-18 07:35:03 +00:00
mfranz
48c8ee3bfc typo: s/atl/alt/ (for "alternatives") 2008-07-24 20:46:30 +00:00
mfranz
4bb77f71d4 argument & parameter completion for bash (instructions inside) 2008-07-24 17:52:04 +00:00
mfranz
43a882b2ec script to output all frequencies for an airport as well as frequencies of
nearby radio navigation facilities and their distance/bearing to the airport
2008-05-04 21:33:16 +00:00
mfranz
93f8c676af fg-check:
- fix rle detection
- check all textures (to catch some forms of curruption)

fg-submit:
- documentation fixes & cleanup
2007-07-28 17:03:10 +00:00
mfranz
a5548068dc check for evil "userarchive" flags (in aircraft xml files) 2007-07-21 21:28:39 +00:00
mfranz
5135c9afd2 add check for thumbnail size 2007-06-05 16:04:24 +00:00
mfranz
8617b0a82a - abort when "cvs up" failed (due to failed connection)
- improve fg-upload example: copying upload address to clipboard (KDE)
2007-03-15 17:05:51 +00:00
mfranz
e8840e4373 can't "exec" fg-upload, as this doesn't trigger the trapZZ 2007-03-11 22:05:37 +00:00
mfranz
962e61903a - more efficient filter routine
- fix wrong log message
- cleanup & cosmetics, as always
2007-03-11 19:30:36 +00:00
mfranz
72ef38722d whoops, need to turn off globbing, or ALLOW * doesn't do what it is supposed to 2007-03-10 21:40:39 +00:00
mfranz
f39ad54d93 before a day passes with no commits at all, better have some fg-submit stuff :-)
- drop the DEFAULT keyword in .fg-submit configuration files. That was
  a silly idea. The default rules are now always appended. One can still
  bypass them by ALLOWing or DENYing anything before, for example, by using
  DENY *, or ALLOW *.
- fix a typo that broke ~/.fg-submitrc loading (but ~/.fg-submit worked anyway)
- some minor improvments, cleanup and all that
2007-03-10 20:46:38 +00:00
mfranz
5b683d1c8b yeah, yet another patch ... :-]
- fix config file name in $HOME; This didn't match the documentation.
  (doesn't cost us anything to check ~/.fg-submit first, and then ~/.fg-submitrc)
- don't use mktemp for the backup files. Some outdated distributions
  (Debian) come with a version that mandates six X, which is just too ugly.
  Just find the first free slot with sequential number. That isn't thread
  safe, but mktemp isn't either, so ...  (Should be using "lockfile", but
  its availability on CygWin is questionable. And it's not *that* important.)
- some more documentation
- some cleanup, too, of course
2007-03-09 19:15:54 +00:00
mfranz
abc3b3ffa1 - rules can be defined in optional .fg-submit config files, via commands
ALLOW, DENY, IGNORE, DEFAULT  ... see documentation on top
- make fg-upload arguments like the documentation says. (I had accidentally
  left $1=$PWD, $2=archive, $3=diff, while it should be $1=archive, $2=diff)
- add -v option (verbose)
2007-03-09 16:22:27 +00:00
mfranz
3f1b379e9a - escape '+' in awk pattern (gawk doesn't need it, but mawk does)
- change the mktemp lines to please Debian's stoneage version ... sigh
- reject archives
2007-03-08 23:16:57 +00:00
mfranz
cbae8f95ac whoops, sorry for the noise -- we don't need that first arg 2007-03-08 17:14:29 +00:00
mfranz
d3e7ca7351 fg-check: speedup, minor fixes, cleanup
fg-submit:
- takes alternative optional basename (used instead of dirname)
- calls optional user defined fg-upload script at the end (example on top)
- minor fixes, different color for changed binary files
- cleanup, improved documentation
2007-03-08 16:45:48 +00:00
mfranz
48a57250be - add fg-check script; Can be used to check source/data before committing or
submitting. Detects various kinds of ugliness, but also reports false
  positives. (People aren't supposed to compress texture filer so save
  40 bytes. ;-)
- bugfix in fg-submit + some more cleanup and cosmetics
2007-03-07 16:26:33 +00:00
mfranz
9a1d1e389a don't move existing diff/tar.bz2 file away asking if it's ok to overwrite,
but rather copy the files to mktemp generated & guaranteed unique files
(don't worry, this is the last patch for today :-)
2007-03-06 21:48:28 +00:00
mfranz
d719f7ac63 cleanup 2007-03-06 21:23:26 +00:00
mfranz
937e8283a3 make unified diff 2007-03-06 20:35:28 +00:00
mfranz
7cea2dd67e script that generates an archive with changed and new files for submission;
works on Unix/Linux/CygWin
2007-03-06 19:23:36 +00:00
mfranz
b075cf5f01 s/--props/--telnet/ (I may do that. I wrote this file. :-) 2007-02-19 16:18:57 +00:00
mfranz
d9015f6923 - check buffer length
- cosmetics
2006-11-23 09:26:43 +00:00
mfranz
f29a6dbf33 - don't use static buffer in class method
- prepend underscore to class member variable names
- cosmetics
2006-11-22 13:47:15 +00:00
mfranz
1d15a9272b George PATTERSON:
"Flightgear.py
- Added the procedures view_next and view_prev

demo.py
- altered the wait five seconds to the new property path and allowed for
the script to be started after five seconds of simulation file
(/sim/time/elapsed-sec).
- the section of code was changed to a pythonism as python does not
support do-while loops, instead you break out of a continuous loop.
- Commented out the fg.wait_for_prop_eq() method as I haven't rewritten
that part of the code yet. Not sure of the best way to do that. Those
lines may not be necessary any more."


mf: removed trailing spaces; I updated the pyc, too, but I really think
    it shouldn't be in CVS at all.(?)
2006-10-29 12:34:26 +00:00
curt
afc849066d Bigger thumbnails. 2006-08-24 15:12:57 +00:00
curt
7282491294 Updateds for v0.9.10-pre3 2006-03-27 19:47:48 +00:00
mfranz
ab7a594dab add workaround for gdb bug
s/calltree/callgrind/
2006-02-09 11:08:17 +00:00
mfranz
f41b0ad951 cosmetics 2006-02-04 23:27:31 +00:00
mfranz
e461edc660 public domain 2006-02-04 23:07:41 +00:00
curt
af6809ac5d Admin updates. 2005-11-05 20:04:04 +00:00
mfranz
c0947d18b9 cvsignore 2005-10-05 11:52:25 +00:00
ehofman
6786e2bbf1 Melchior FRANZ:
There weren't changes to this script in a while -- it almost looks
like dead code, but isn't. I'm using this regularly. valgrind works
better than ever (version 3.0 coming out soon, and the alpha already
very usable). New address: http://www.valgrind.org/
2005-04-19 12:34:38 +00:00